package com.xbongbong.paas.script.controller;


import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xbongbong.crm.service.impl.SearchCustomerServiceImpl;
import com.xbongbong.paas.constant.PaasConstant;
import com.xbongbong.paas.constant.SizeConstant;
import com.xbongbong.paas.domain.entity.PaasFormDataEntity;
import com.xbongbong.paas.domain.entity.PaasFormExplainEntity;
import com.xbongbong.paas.domain.entity.PaasListGroupEntity;
import com.xbongbong.paas.domain.entity.ext.PaasFormDataEntityExt;
import com.xbongbong.paas.domain.entity.ext.PaasFormEntityExt;
import com.xbongbong.paas.elasticsearch.model.PaasEsModel;
import com.xbongbong.paas.elasticsearch.model.impl.PaasEsModelImpl;
import com.xbongbong.paas.elasticsearch.pojo.XbbAggregatedPage;
import com.xbongbong.paas.elasticsearch.pojo.dto.InsertDTO;
import com.xbongbong.paas.elasticsearch.util.EsHelper;
import com.xbongbong.paas.elasticsearch.util.EsUtil;
import com.xbongbong.paas.elasticsearch.util.XbbElasticsearchRestTemplate;
import com.xbongbong.paas.enums.DefaultTypeEnum;
import com.xbongbong.paas.enums.DelEnum;
import com.xbongbong.paas.enums.FieldTypeEnum;
import com.xbongbong.paas.enums.FlowStatusEnum;
import com.xbongbong.paas.enums.IndexTypeEnum;
import com.xbongbong.paas.enums.PaymentSheetTypeEnum;
import com.xbongbong.paas.field.FieldAttrEntity;
import com.xbongbong.paas.field.LinkInfoPojo;
import com.xbongbong.paas.field.LinkedAttrPoJo;
import com.xbongbong.paas.field.SubFormPoJo;
import com.xbongbong.paas.field.VisibleRulePoJo;
import com.xbongbong.paas.help.FormDataFormExplainHelper;
import com.xbongbong.paas.help.ProUpdateHelp;
import com.xbongbong.paas.help.subform.TransferSubFormHelper;
import com.xbongbong.paas.model.PaasFormExplainModel;
import com.xbongbong.paas.model.PaasFormModel;
import com.xbongbong.paas.model.PaasListGroupModel;
import com.xbongbong.paas.model.PaasProcessNodeTaskModel;
import com.xbongbong.paas.model.PaasProcessTaskModel;
import com.xbongbong.paas.model.SearchCustomerCompanyModel;
import com.xbongbong.paas.model.SearchCustomerUserModel;
import com.xbongbong.paas.pojo.SummaryDataPoJo;
import com.xbongbong.paas.pojo.dto.CompanyRuleSetDTO;
import com.xbongbong.paas.pojo.dto.FixDataJobBatchDTO;
import com.xbongbong.paas.pojo.dto.FixDataJobDTO;
import com.xbongbong.paas.pojo.dto.FormDataUpdateGetDTO;
import com.xbongbong.paas.script.help.ScriptEsHelper;
import com.xbongbong.paas.script.pojo.ListVO;
import com.xbongbong.paas.service.PaasAppService;
import com.xbongbong.paas.toolbox.exception.XbbException;
import com.xbongbong.paas.toolbox.util.Arith;
import com.xbongbong.paas.toolbox.util.BeanUtil;
import com.xbongbong.paas.toolbox.util.CollectionsUtil;
import com.xbongbong.paas.toolbox.util.CommentUtil;
import com.xbongbong.paas.toolbox.util.DateTimeUtil;
import com.xbongbong.paas.toolbox.util.DateUtil;
import com.xbongbong.paas.toolbox.util.JsonHelperUtil;
import com.xbongbong.paas.toolbox.util.StringUtil;
import com.xbongbong.paas.toolbox.wrap.XbbResponse;
import com.xbongbong.paas.util.ExplainUtil;
import com.xbongbong.pro.config.ProBaseConfig;
import com.xbongbong.pro.constant.ElasticConstant;
import com.xbongbong.pro.constant.XbbProConstant;
import com.xbongbong.pro.domain.entity.FormConfigEntity;
import com.xbongbong.pro.domain.entity.SearchCustomerCompanyEntity;
import com.xbongbong.pro.domain.entity.SearchCustomerUserEntity;
import com.xbongbong.pro.domain.entity.UpdateDataEntity;
import com.xbongbong.pro.enums.SaasMarkEnum;
import com.xbongbong.pro.enums.SoukeMealEnum;
import com.xbongbong.pro.enums.errorcodes.SystemErrorCodeEnum;
import com.xbongbong.pro.script.pojo.dto.FixContractDTO;
import com.xbongbong.pro.script.pojo.dto.FixFormDTO;
import com.xbongbong.pro.script.pojo.dto.RepairContractBadAmountDTO;
import com.xbongbong.pro.script.pojo.dto.RepairInvoiceAmountDTO;
import com.xbongbong.pro.script.pojo.dto.RepairInvoiceRelationMoneyDTO;
import com.xbongbong.pro.script.pojo.dto.UpdateDataDTO;
import com.xbongbong.pro.script.pojo.vo.ScriptVO;
import com.xbongbong.pro.searchcustomer.pojo.dto.SearchCustomerDTO;
import com.xbongbong.saas.constant.BasicConstant;
import com.xbongbong.saas.constant.PageConstant;
import com.xbongbong.saas.constant.ParameterConstant;
import com.xbongbong.saas.constant.StringConstant;
import com.xbongbong.saas.domain.entity.ContactUserEntity;
import com.xbongbong.saas.domain.entity.ContractProductEntity;
import com.xbongbong.saas.domain.entity.ContractUserEntity;
import com.xbongbong.saas.domain.entity.CustomerUserEntity;
import com.xbongbong.saas.domain.entity.InstockProductEntity;
import com.xbongbong.saas.domain.entity.OpportunityUserEntity;
import com.xbongbong.saas.domain.entity.OutstockProductEntity;
import com.xbongbong.saas.domain.entity.PayPlanUserEntity;
import com.xbongbong.saas.domain.entity.PaymentBalanceEntity;
import com.xbongbong.saas.domain.entity.PaymentUserEntity;
import com.xbongbong.saas.domain.entity.ProductWarehouseEntity;
import com.xbongbong.saas.domain.entity.PurchaseUserEntity;
import com.xbongbong.saas.domain.entity.SpecificationEntity;
import com.xbongbong.saas.domain.entity.SupplierProductEntity;
import com.xbongbong.saas.domain.entity.WorkOrderEntity;
import com.xbongbong.saas.domain.entity.WorkOrderExplainEntity;
import com.xbongbong.saas.domain.entity.WorkOrderProductEntity;
import com.xbongbong.saas.domain.entity.ext.ContractEntityExt;
import com.xbongbong.saas.domain.entity.ext.OutstockEntityExt;
import com.xbongbong.saas.domain.entity.ext.PayPlanEntityExt;
import com.xbongbong.saas.domain.entity.ext.PaymentEntityExt;
import com.xbongbong.saas.domain.entity.ext.PaymentSheetEntityExt;
import com.xbongbong.saas.domain.entity.ext.RefundEntityExt;
import com.xbongbong.saas.domain.entity.ext.WorkReportEntityExt;
import com.xbongbong.saas.enums.ForbiddenSettingEnum;
import com.xbongbong.saas.enums.ListGroupEnum;
import com.xbongbong.saas.enums.OutstockTypeEnum;
import com.xbongbong.saas.enums.RuleSettingEnum;
import com.xbongbong.saas.enums.SelectProductEnum;
import com.xbongbong.saas.enums.ShowTypeEnum;
import com.xbongbong.saas.enums.XbbRefTypeEnum;
import com.xbongbong.saas.enums.business.AssembleEnum;
import com.xbongbong.saas.enums.business.BomBillEnum;
import com.xbongbong.saas.enums.business.ContactEnum;
import com.xbongbong.saas.enums.business.ContractEnum;
import com.xbongbong.saas.enums.business.ContractOutstockEnum;
import com.xbongbong.saas.enums.business.CustomerManagementEnum;
import com.xbongbong.saas.enums.business.InstockEnum;
import com.xbongbong.saas.enums.business.InventoryEnum;
import com.xbongbong.saas.enums.business.OriStockEnum;
import com.xbongbong.saas.enums.business.OutstockEnum;
import com.xbongbong.saas.enums.business.PayPlanEnum;
import com.xbongbong.saas.enums.business.PaymentEnum;
import com.xbongbong.saas.enums.business.PaymentSheetEnum;
import com.xbongbong.saas.enums.business.ProductEnum;
import com.xbongbong.saas.enums.business.ProductionInstockEnum;
import com.xbongbong.saas.enums.business.ProductionMaterielOutstockEnum;
import com.xbongbong.saas.enums.business.ProductionOrderEnum;
import com.xbongbong.saas.enums.business.PurchaseEnum;
import com.xbongbong.saas.enums.business.PurchaseInstockEnum;
import com.xbongbong.saas.enums.business.QuotationEnum;
import com.xbongbong.saas.enums.business.RefundEnum;
import com.xbongbong.saas.enums.business.RefundInstockEnum;
import com.xbongbong.saas.enums.business.ReturnedMaterielInstockEnum;
import com.xbongbong.saas.enums.business.ReturnedPurchaseEnum;
import com.xbongbong.saas.enums.business.ReturnedPurchaseOutstockEnum;
import com.xbongbong.saas.enums.business.SalesOpportunityEnum;
import com.xbongbong.saas.enums.business.SupplierEnum;
import com.xbongbong.saas.enums.business.TransferEnum;
import com.xbongbong.saas.enums.business.WorkOrderEnum;
import com.xbongbong.saas.enums.business.WorkOrderOutstockEnum;
import com.xbongbong.saas.enums.business.WorkReportDailyEnum;
import com.xbongbong.saas.enums.business.WorkReportFieldEnum;
import com.xbongbong.saas.enums.business.WorkReportMonthlyEnum;
import com.xbongbong.saas.enums.business.WorkReportWeeklyEnum;
import com.xbongbong.saas.enums.dictionary.AllInBoundEnum;
import com.xbongbong.saas.enums.dictionary.IsBadEnum;
import com.xbongbong.saas.enums.dictionary.PaymentStatusEnum;
import com.xbongbong.saas.enums.product.AssembleInProductEnum;
import com.xbongbong.saas.enums.product.AssembleProductEnum;
import com.xbongbong.saas.enums.product.BomFinishProductEnum;
import com.xbongbong.saas.enums.product.BomMaterielProductEnum;
import com.xbongbong.saas.enums.product.ContractOutstockProductEnum;
import com.xbongbong.saas.enums.product.ContractProductEnum;
import com.xbongbong.saas.enums.product.InstockProductEnum;
import com.xbongbong.saas.enums.product.InventoryProductEnum;
import com.xbongbong.saas.enums.product.OpportunityProductEnum;
import com.xbongbong.saas.enums.product.OriStockProductEnum;
import com.xbongbong.saas.enums.product.OutstockProductEnum;
import com.xbongbong.saas.enums.product.ProductionInstockProductEnum;
import com.xbongbong.saas.enums.product.ProductionMaterielOutstockProductEnum;
import com.xbongbong.saas.enums.product.ProductionOrderFinishProductEnum;
import com.xbongbong.saas.enums.product.ProductionOrderMaterielProductEnum;
import com.xbongbong.saas.enums.product.PurchaseInstockProductEnum;
import com.xbongbong.saas.enums.product.PurchaseProductEnum;
import com.xbongbong.saas.enums.product.QuotationProductEnum;
import com.xbongbong.saas.enums.product.RefundInstockProductEnum;
import com.xbongbong.saas.enums.product.RefundProductEnum;
import com.xbongbong.saas.enums.product.ReturnPurchaseProductEnum;
import com.xbongbong.saas.enums.product.ReturnedMaterielInstockProductEnum;
import com.xbongbong.saas.enums.product.ReturnedPurchaseOutstockProductEnum;
import com.xbongbong.saas.enums.product.SupplierProductEnum;
import com.xbongbong.saas.enums.product.TransferProductEnum;
import com.xbongbong.saas.enums.product.WorkOrderOutstockProductEnum;
import com.xbongbong.saas.enums.product.WorkOrderProductEnum;
import com.xbongbong.saas.enums.subform.ContactTeamEnum;
import com.xbongbong.saas.enums.subform.ContractProductSubFormEnum;
import com.xbongbong.saas.enums.subform.ContractTeamEnum;
import com.xbongbong.saas.enums.subform.CustomerTeamEnum;
import com.xbongbong.saas.enums.subform.OpportunityTeamEnum;
import com.xbongbong.saas.enums.subform.PaymentTeamEnum;
import com.xbongbong.saas.enums.subform.ProductWarehouseSubFormEnum;
import com.xbongbong.saas.help.SaasProductHelp;
import com.xbongbong.saas.help.workflow.PayAndPaymentSheetHelp;
import com.xbongbong.saas.model.CommunicatePlanUserModel;
import com.xbongbong.saas.model.ContactUserModel;
import com.xbongbong.saas.model.ContractModel;
import com.xbongbong.saas.model.ContractProductModel;
import com.xbongbong.saas.model.ContractUserModel;
import com.xbongbong.saas.model.CustomerModel;
import com.xbongbong.saas.model.CustomerUserModel;
import com.xbongbong.saas.model.FormConfigModel;
import com.xbongbong.saas.model.IndexTypeModel;
import com.xbongbong.saas.model.OpportunityUserModel;
import com.xbongbong.saas.model.OutstockModel;
import com.xbongbong.saas.model.OutstockProductModel;
import com.xbongbong.saas.model.PayPlanModel;
import com.xbongbong.saas.model.PayPlanUserModel;
import com.xbongbong.saas.model.PaymentBalanceModel;
import com.xbongbong.saas.model.PaymentModel;
import com.xbongbong.saas.model.PaymentSheetModel;
import com.xbongbong.saas.model.PaymentUserModel;
import com.xbongbong.saas.model.ProductModel;
import com.xbongbong.saas.model.ProductWarehouseModel;
import com.xbongbong.saas.model.PurchaseModel;
import com.xbongbong.saas.model.PurchaseUserModel;
import com.xbongbong.saas.model.ReturnedPurchaseModel;
import com.xbongbong.saas.model.SpecificationModel;
import com.xbongbong.saas.model.SupplierProductModel;
import com.xbongbong.saas.model.WorkOrderExplainModel;
import com.xbongbong.saas.model.WorkOrderModel;
import com.xbongbong.saas.model.WorkOrderProductModel;
import com.xbongbong.saas.model.WorkReportModel;
import com.xbongbong.saas.script.help.InitExplainsHelper;
import com.xbongbong.saas.script.tempenum.TempContractEnum;
import com.xbongbong.saas.script.tempenum.TempProductEnum;
import com.xbongbong.saas.script.tempenum.TempPurchaseEnum;
import com.xbongbong.saas.script.tempenum.TempQuotationEnum;
import com.xbongbong.saas.script.tempenum.TempRefundEnum;
import com.xbongbong.saas.script.tempenum.TempReturnedPurchaseEnum;
import com.xbongbong.saas.script.tempenum.TempSalesOpportunityEnum;
import com.xbongbong.saas.script.tempenum.product.TempAssembleInProductEnum;
import com.xbongbong.saas.script.tempenum.product.TempAssembleProductEnum;
import com.xbongbong.saas.script.tempenum.product.TempBomFinishProductEnum;
import com.xbongbong.saas.script.tempenum.product.TempBomMaterieProductEnum;
import com.xbongbong.saas.script.tempenum.product.TempContractOutstockProductEnum;
import com.xbongbong.saas.script.tempenum.product.TempContractProductEnum;
import com.xbongbong.saas.script.tempenum.product.TempInstockProductEnum;
import com.xbongbong.saas.script.tempenum.product.TempInventoryProductEnum;
import com.xbongbong.saas.script.tempenum.product.TempOpportunityProductEnum;
import com.xbongbong.saas.script.tempenum.product.TempOriStockProductEnum;
import com.xbongbong.saas.script.tempenum.product.TempOutstockProductEnum;
import com.xbongbong.saas.script.tempenum.product.TempProductionInstockProductEnum;
import com.xbongbong.saas.script.tempenum.product.TempProductionMaterielOutstockProductEnum;
import com.xbongbong.saas.script.tempenum.product.TempProductionOrderFinishProductEnum;
import com.xbongbong.saas.script.tempenum.product.TempProductionOrderMaterieProductEnum;
import com.xbongbong.saas.script.tempenum.product.TempPurchaseInstockProductEnum;
import com.xbongbong.saas.script.tempenum.product.TempPurchaseProductEnum;
import com.xbongbong.saas.script.tempenum.product.TempQuotationProductEnum;
import com.xbongbong.saas.script.tempenum.product.TempRefundInstockProductEnum;
import com.xbongbong.saas.script.tempenum.product.TempRefundProductEnum;
import com.xbongbong.saas.script.tempenum.product.TempReturnPurchaseProductEnum;
import com.xbongbong.saas.script.tempenum.product.TempReturnedMaterielInstockProductEnum;
import com.xbongbong.saas.script.tempenum.product.TempReturnedPurchaseOutstockProductEnum;
import com.xbongbong.saas.script.tempenum.product.TempSupplierProductEnum;
import com.xbongbong.saas.script.tempenum.product.TempTransferProductEnum;
import com.xbongbong.saas.script.tempenum.product.TempWorkOrderOutstockProductEnum;
import com.xbongbong.saas.script.tempenum.product.TempWorkOrderProductEnum;
import com.xbongbong.saas.service.FundFixDataService;
import com.xbongbong.saas.service.InstockProductService;
import com.xbongbong.saas.service.JsonSetService;
import com.xbongbong.saas.service.PaymentService;
import com.xbongbong.saas.service.PurchaseService;
import com.xbongbong.saas.service.RepairDataService;
import com.xbongbong.saas.service.RepairExplainService;
import com.xbongbong.saas.service.toolbox.help.FundMoneyHelp;
import com.xbongbong.saas.toolbox.help.FastJsonHelper;
import com.xbongbong.sys.domain.entity.CompanyEntity;
import com.xbongbong.sys.enums.RoleEnum;
import com.xbongbong.sys.model.CompanyModel;
import org.apache.commons.collections4.CollectionUtils;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.support.WriteRequest;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.domain.PageRequest;
import org.springframework.http.MediaType;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

import static com.xbongbong.paas.elasticsearch.constant.EsNormalConstant.MINI_MUM_SHOULD_MATCH;
import static org.elasticsearch.index.query.QueryBuilders.boolQuery;
import static org.elasticsearch.index.query.QueryBuilders.existsQuery;
import static org.elasticsearch.index.query.QueryBuilders.rangeQuery;
import static org.elasticsearch.index.query.QueryBuilders.termQuery;
import static org.elasticsearch.index.query.QueryBuilders.termsQuery;

/**
 * @author feng.zheng
 * @version v1.0
 * @date 2019/9/9 15:15
 * @since v1.0
 */
@RestController
@RequestMapping(XbbProConstant.API_ROOT_PREFIX + "/script/fixData")
public class FixDataScriptController {
    private static final Logger LOG = LoggerFactory.getLogger(FixDataScriptController.class);
    @Resource
    private ProBaseConfig proBaseConfig;
    @Resource
    private PaymentModel paymentModel;
    @Resource
    private EsHelper esHelper;
    @Resource
    private PaasEsModel paasEsModel;
    @Resource
    private CustomerUserModel customerUserModel;
    @Resource
    private ContractUserModel contractUserModel;
    @Resource
    private PaymentUserModel paymentUserModel;
    @Resource
    private ScriptEsHelper scriptEsHelper;
    @Resource
    private XbbElasticsearchRestTemplate xbbElasticsearchRestTemplate;
    @Resource
    private CommunicatePlanUserModel communicatePlanUserModel;
    @Resource
    private PayPlanModel payPlanModel;
    @Resource
    private PayPlanUserModel payPlanUserModel;
    @Resource
    private PurchaseUserModel purchaseUserModel;
    @Resource
    private PaasProcessTaskModel paasProcessTaskModel;
    @Resource
    private PaasProcessNodeTaskModel paasProcessNodeTaskModel;
    @Resource
    private CustomerModel customerModel;
    @Resource
    private PaasEsModelImpl paasEsModelImpl;
    @Resource
    private ProductModel productModel;
    @Resource
    private PurchaseService purchaseService;
    @Resource
    private PurchaseModel purchaseModel;
    @Resource
    private ContractModel contractModel;
    @Resource
    private CompanyModel companyModel;
    @Resource
    private OpportunityUserModel opportunityUserModel;
    @Resource
    private PaasFormExplainModel paasFormExplainModel;
    @Resource
    private PaasFormModel paasFormModel;
    @Resource
    private WorkOrderExplainModel workOrderExplainModel;

    @Resource
    private ProductWarehouseModel productWarehouseModel;
    @Resource
    private JsonSetService jsonSetService;
    @Resource
    private SearchCustomerCompanyModel searchCustomerCompanyModel;
    @Resource
    private SearchCustomerUserModel searchCustomerUserModel;
    @Resource
    private SpecificationModel specificationModel;
    @Resource
    private ContactUserModel contactUserModel;
    @Resource
    private ReturnedPurchaseModel returnedPurchaseModel;
    @Resource
    private WorkReportModel workReportModel;
    @Resource
    private RepairExplainService repairExplainService;
    @Resource
    private InstockProductService instockProductService;
    @Resource
    private WorkOrderProductModel workOrderProductModel;
    @Resource
    private WorkOrderModel workOrderModel;
    @Resource
    private ContractProductModel contractProductModel;
    @Resource
    private SupplierProductModel supplierProductModel;
    @Resource
    private FundMoneyHelp fundMoneyHelp;
    @Resource
    private OutstockModel outstockModel;
    @Resource
    private PaymentService paymentService;
    @Resource
    private PaymentSheetModel paymentSheetModel;
    @Resource
    private PaymentBalanceModel paymentBalanceModel;
    @Resource
    private SearchCustomerServiceImpl searchCustomerServiceImpl;
    @Resource
    private TransferSubFormHelper transferSubFormHelper;
    @Resource
    private ProUpdateHelp proUpdateHelp;
    @Resource
    private FormConfigModel formConfigModel;
    @Resource
    private PaasListGroupModel paasListGroupModel;
    @Resource
    private PaasAppService paasAppService;
    @Resource
    private OutstockProductModel outstockProductModel;
    @Resource
    private FundFixDataService fundFixDataService;
    @Resource
    private PayAndPaymentSheetHelp payAndPaymentSheetHelp;
    @Resource
    private RepairDataService repairDataService;
    @Resource
    private IndexTypeModel indexTypeModel;


    /**
     * 修复应收款数据库中存在而ES中不存在的数据
     *
     * @author GuoJun.HU
     * @date 2019/8/12 14:31
     * @since V1.0
     */
    @RequestMapping(value = "/fixPaymentNotExistInES", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String fixPaymentNotExistInES(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006);
        }
        List<String> corpidList = fixDataJobDTO.getCorpidList();
        if (corpidList == null || corpidList.isEmpty()) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, "公司id不能为空");
        }
        String corpid = corpidList.get(0);

        Map<String, Object> param = new HashMap<>(16);
        param.put("corpid", corpid);
        param.put("del", 0);
        Integer totalCount = paymentModel.getEntitysCount(param);
        LOG.warn("数据库中共有" + totalCount + "条数据");

        int pageSize = 100;
        int totalPage = (totalCount % pageSize == 0) ? (totalCount / pageSize) : (totalCount / pageSize) + 1;
        int lastPageSize = (totalCount % pageSize == 0) ? pageSize : (totalCount % pageSize);

        for (int page = 0; page < totalPage; page++) {
            if (page == totalPage - 1) {
                param.put("pageNum", lastPageSize);
            } else {
                param.put("pageNum", pageSize);
            }
            param.put("start", page * pageSize);
            List<PaymentEntityExt> paymentEntityDBList = paymentModel.findEntitys(param);
            if (paymentEntityDBList.isEmpty()) {
                continue;
            }

            List<Long> paymentIdIn = new ArrayList<>();
            for (PaymentEntityExt paymentEntityExt : paymentEntityDBList) {
                paymentIdIn.add(paymentEntityExt.getId());
            }

            BoolQueryBuilder boolQueryBuilder = boolQuery();
            boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
            boolQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
            boolQueryBuilder.filter(termsQuery(FieldTypeEnum.DATAID.getAlias(), paymentIdIn));
            List<String> fieldList = new ArrayList<>();
            fieldList.add(FieldTypeEnum.DATAID.getAlias());
            fieldList.add("corpid");
            List<PaymentEntityExt> paymentEntityESList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_PAYMENT, boolQueryBuilder, PaymentEntityExt.class, fieldList);
            LOG.warn("第" + (page + 1) + "页ES数据和数据库数据比较");

            if (Objects.equals(paymentEntityESList.size(), paymentEntityDBList.size())) {
                continue;
            }

            Set<String> esExistSet = new HashSet<>();
            for (PaymentEntityExt paymentEntityExt : paymentEntityESList) {
                String key = paymentEntityExt.getDataId() + "_" + paymentEntityExt.getCorpid();
                esExistSet.add(key);
            }

            List<InsertDTO> needInsertESList = new ArrayList<>();
            List<UpdateDataEntity> list = new ArrayList<>();
            for (PaymentEntityExt paymentEntityExt : paymentEntityDBList) {
                String key = paymentEntityExt.getId() + "_" + paymentEntityExt.getCorpid();
                if (!esExistSet.contains(key)) {
                    InsertDTO insertDTO = new InsertDTO();
                    insertDTO.setWaitUntil(WriteRequest.RefreshPolicy.NONE);
                    insertDTO.setEsId(paymentEntityExt.getCorpid() + "_" + paymentEntityExt.getId());
                    paymentEntityExt.setDataId(paymentEntityExt.getId());
                    try {
                        JSONObject dataObj = paymentEntityExt.getData();
                        if (dataObj != null) {
                            dataObj.forEach((key1, value) -> {
                                if (key1.startsWith(FieldTypeEnum.TEXT.getAlias()) && value instanceof Map) {
                                    dataObj.put(key1, null);
                                }
                            });
                            String estimateTimeStr = dataObj.getString(PaymentEnum.ESTIMATE_TIME.getAttr());
                            String realPayTimeStr = dataObj.getString(PaymentEnum.REAL_PAY_TIME.getAttr());
                            if (Objects.nonNull(realPayTimeStr) && estimateTimeStr.contains(".")) {
                                Long estimateTime = (new BigDecimal(estimateTimeStr)).longValue();
                                dataObj.put(PaymentEnum.ESTIMATE_TIME.getAttr(), estimateTime);
                            }
                            if (Objects.nonNull(realPayTimeStr) && realPayTimeStr.contains(".")) {
                                Long realPayTime = (new BigDecimal(realPayTimeStr)).longValue();
                                dataObj.put(PaymentEnum.REAL_PAY_TIME.getAttr(), realPayTime);
                            }
                        }
                        PaasFormDataEntity paasFormDataEntity = new PaasFormDataEntity();
                        BeanUtil.copyProperties(paymentEntityExt, paasFormDataEntity);
                        insertDTO.setSource(BeanUtil.convertBean2Map(paasFormDataEntity));
                        insertDTO.setIndexTypeEnum(IndexTypeEnum.IDX_SAAS_PAYMENT);
                        needInsertESList.add(insertDTO);
                        list.add(ExplainUtil.getUpdateData(paymentEntityExt.getId(), dataObj, corpid));
                    } catch (Exception e) {
                        LOG.warn(e.getMessage());
                    }
                }
            }

            if (!needInsertESList.isEmpty()) {
                paasEsModel.insertBatch(needInsertESList, WriteRequest.RefreshPolicy.NONE);
                paymentModel.updateBatch(list, corpid);
                LOG.warn("批量插入ES数据" + needInsertESList.size() + "条");
            }
        }

        return null;
    }

    @RequestMapping(value = "/fixPaymentDatabase", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String fixPaymentDatabase(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006);
        }
        List<String> corpidList = fixDataJobDTO.getCorpidList();
        if (corpidList == null || corpidList.isEmpty()) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001, "公司id不能为空");
        }
        String corpid = corpidList.get(0);

        Map<String, Object> param = new HashMap<>(16);
        param.put("corpid", corpid);
        param.put("del", 0);
        Integer totalCount = paymentModel.getEntitysCount(param);
        LOG.warn("数据库中共有" + totalCount + "条数据");

        int pageSize = 100;
        int totalPage = (totalCount % pageSize == 0) ? (totalCount / pageSize) : (totalCount / pageSize) + 1;
        int lastPageSize = (totalCount % pageSize == 0) ? pageSize : (totalCount % pageSize);
        int count = 0;

        for (int page = 0; page < totalPage; page++) {
            if (page == totalPage - 1) {
                param.put("pageNum", lastPageSize);
            } else {
                param.put("pageNum", pageSize);
            }
            param.put("start", page * pageSize);
            List<PaymentEntityExt> paymentEntityDBList = paymentModel.findEntitys(param);
            if (paymentEntityDBList.isEmpty()) {
                continue;
            }

            List<UpdateDataEntity> needUpdateList = new ArrayList<>();
            for (PaymentEntityExt paymentEntityExt : paymentEntityDBList) {
                try {
                    boolean isNeedUpdate = false;
                    JSONObject dataObj = paymentEntityExt.getData();
                    Long paymentId = paymentEntityExt.getId();
                    if (dataObj != null) {
                        for (Map.Entry<String, Object> entry : dataObj.entrySet()) {
                            String key1 = entry.getKey();
                            Object value = entry.getValue();
                            if (key1.startsWith(FieldTypeEnum.TEXT.getAlias()) && value instanceof Map) {
                                isNeedUpdate = true;
                                dataObj.put(key1, null);
                            }
                        }
                        String estimateTimeStr = dataObj.getString(PaymentEnum.ESTIMATE_TIME.getAttr());
                        String realPayTimeStr = dataObj.getString(PaymentEnum.REAL_PAY_TIME.getAttr());
                        if (Objects.nonNull(realPayTimeStr) && estimateTimeStr.contains(".")) {
                            Long estimateTime = (new BigDecimal(estimateTimeStr)).longValue();
                            dataObj.put(PaymentEnum.ESTIMATE_TIME.getAttr(), estimateTime);
                            isNeedUpdate = true;
                        }
                        if (Objects.nonNull(realPayTimeStr) && realPayTimeStr.contains(".")) {
                            Long realPayTime = (new BigDecimal(realPayTimeStr)).longValue();
                            dataObj.put(PaymentEnum.REAL_PAY_TIME.getAttr(), realPayTime);
                            isNeedUpdate = true;
                        }
                    }
                    if (isNeedUpdate) {
                        UpdateDataEntity updateDataEntity = ExplainUtil.getUpdateData(paymentId, dataObj, corpid);
                        needUpdateList.add(updateDataEntity);
                        count++;
                    }
                } catch (Exception e) {
                    LOG.warn(e.getMessage());
                }
            }

            if (!needUpdateList.isEmpty()) {
                paymentModel.updateBatch(needUpdateList, corpid);
                LOG.warn("批量更新数据库数据" + needUpdateList.size() + "条");
            }
        }
        return "批量更新数据库数据" + count + "条";
    }


    @RequestMapping(value = "/fixCustomerTeam", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String fixCustomerTeam(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        List<String> corpidList = fixDataJobDTO.getCorpidList();
        for (String corpid : corpidList) {
            Long dataDataMark = 0L;
            List<PaasFormDataEntityExt> paasFormDataEntityExtList = new ArrayList<>();
            paasFormDataEntityExtList.add(new PaasFormDataEntityExt());
            while (!paasFormDataEntityExtList.isEmpty()) {
                BoolQueryBuilder boolQueryBuilder = boolQuery();
                boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
                boolQueryBuilder.filter(termQuery(CustomerManagementEnum.getEsAttr4Keyword(CustomerManagementEnum.IS_PUBLIC), 0));
                boolQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
                IndexTypeEnum indexTypeEnum = indexTypeModel.getCustomerIndex(corpid, XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode(), SaasMarkEnum.SAAS.getCode());
                ListVO listVO = scriptEsHelper.list(boolQueryBuilder, 100, PaasFormDataEntityExt.class, indexTypeEnum, dataDataMark);
                paasFormDataEntityExtList = listVO.getList();
                dataDataMark = listVO.getDataIdMark();
                if (paasFormDataEntityExtList.isEmpty()) {
                    continue;
                }
                List<Long> customerIdList = new ArrayList<>();
                for (PaasFormDataEntityExt entityExt : paasFormDataEntityExtList) {
                    customerIdList.add(entityExt.getDataId());
                }
                List<Long> hasTeamCustomerIdList = customerUserModel.getDataIdForTempJob(corpid, customerIdList);
                customerIdList.removeAll(hasTeamCustomerIdList);
                if (customerIdList.isEmpty()) {
                    continue;
                }
                LOG.warn("fixCustomerTeam:" + JSONArray.toJSONString(customerIdList));
                List<CustomerUserEntity> insertList = new ArrayList<>();
                for (Long customerId : customerIdList) {
                    CustomerUserEntity customerUserEntity = new CustomerUserEntity();
                    customerUserEntity.setCorpid(corpid);
                    customerUserEntity.setUserId("12653822631289754");
                    customerUserEntity.setUserName("黄瑞");
                    customerUserEntity.setDataId(customerId);
                    customerUserEntity.setIsMain(1);
                    customerUserEntity.setDistributionTime(0L);
                    customerUserEntity.setBackTime(0L);
                    customerUserEntity.setAddTime(DateTimeUtil.getInt());
                    customerUserEntity.setUpdateTime(DateTimeUtil.getInt());
                    customerUserEntity.setDel(0);
                    insertList.add(customerUserEntity);
                }
                if (!insertList.isEmpty()) {
                    customerUserModel.insertBatch(insertList, false);
                }
            }
        }
        LOG.warn("fixCustomerTeam over");
        return null;
    }

    @RequestMapping(value = "/fixPaymentTeam", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String fixPaymentTeam(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        Map<String, Object> param = new HashMap<>(16);
        param.put(ParameterConstant.CORPID, fixDataJobDTO.getCorpid());
        param.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        Integer totalCount = paymentModel.getEntitysCount(param);
        LOG.warn("该公司数据库中共有回款" + totalCount + "条数据");

        int pageSize = 1000;
        int totalPage = (totalCount % pageSize == 0) ? (totalCount / pageSize) : (totalCount / pageSize) + 1;
        int lastPageSize = (totalCount % pageSize == 0) ? pageSize : (totalCount % pageSize);

        for (int page = 0; page < totalPage; page++) {
            param.remove("contractIdIn");
            if (page == totalPage - 1) {
                param.put("pageNum", lastPageSize);
            } else {
                param.put("pageNum", pageSize);
            }
            param.put("start", page * pageSize);
            LOG.warn("第" + page + "页开始");
            List<PaymentEntityExt> paymentEntityDBList = paymentModel.findEntitys(param);
            if (paymentEntityDBList.isEmpty()) {
                continue;
            }
            List<Long> contractIdIn = new ArrayList<>();
            List<Long> paymentIdIn = new ArrayList<>();
            Map<Long, Long> payment2ContractMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            for (PaymentEntityExt paymentEntityExt : paymentEntityDBList) {
                Long contractId = null;
                try {
                    contractId = paymentEntityExt.getData().getLong(PaymentEnum.CONTRACT.getAttr());
                } catch (Exception e) {
                }
                if (contractId != null) {
                    payment2ContractMap.put(paymentEntityExt.getId(), contractId);
                    contractIdIn.add(contractId);
                }
                paymentIdIn.add(paymentEntityExt.getId());
            }
            param.remove("pageNum");
            param.remove("contractIdIn");
            param.put("paymentIdIn", paymentIdIn);
            List<PaymentUserEntity> paymentUserEntityList = paymentUserModel.findEntitys(param);
            param.remove("paymentIdIn");
            param.put("contractIdIn", contractIdIn);
            List<ContractUserEntity> contractUserEntityList = contractUserModel.findEntitys(param);
            Map<Long, List<ContractUserEntity>> contractUserMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            contractUserEntityList.forEach(contractUserEntity -> {
                List<ContractUserEntity> userEntityList = new ArrayList<>();
                if (contractUserMap.containsKey(contractUserEntity.getDataId())) {
                    userEntityList = contractUserMap.get(contractUserEntity.getDataId());
                }
                userEntityList.add(contractUserEntity);
                contractUserMap.put(contractUserEntity.getDataId(), userEntityList);
            });
            List<PaymentUserEntity> insertPaymentUserEntityList = new ArrayList<>();
            payment2ContractMap.entrySet().forEach(entry -> {
                if (CollectionUtils.isNotEmpty(contractUserMap.get(entry.getValue()))) {
                    for (ContractUserEntity contractUserEntity : contractUserMap.get(entry.getValue())) {
                        PaymentUserEntity paymentUserEntity = new PaymentUserEntity();
                        BeanUtil.copyProperties(contractUserEntity, paymentUserEntity);
                        paymentUserEntity.setId(null);
                        paymentUserEntity.setDataId(entry.getKey());
                        paymentUserEntity.setContractId(contractUserEntity.getDataId());
                        paymentUserEntity.setRefType(XbbRefTypeEnum.CONTRACT.getCode());
                        insertPaymentUserEntityList.add(paymentUserEntity);
                    }
                }
            });
            if (CollectionUtils.isNotEmpty(paymentUserEntityList)) {
                paymentUserModel.batchDelete(fixDataJobDTO.getCorpid(), paymentUserEntityList);
            }
            if (CollectionUtils.isNotEmpty(insertPaymentUserEntityList)) {
                paymentUserModel.insertBatch(insertPaymentUserEntityList);
            }
            LOG.warn("第" + page + "页结束");
        }
        LOG.warn("操作成功");
        return null;
    }

    @RequestMapping(value = "/fixPayPlanTeam", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String fixPayPlanTeam(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        Map<String, Object> param = new HashMap<>(16);
        param.put(ParameterConstant.CORPID, fixDataJobDTO.getCorpid());
        param.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
        Integer totalCount = payPlanModel.getEntitysCount(param);
        LOG.warn("该公司数据库中共有付款计划" + totalCount + "条数据");

        int pageSize = 1000;
        int totalPage = (totalCount % pageSize == 0) ? (totalCount / pageSize) : (totalCount / pageSize) + 1;
        int lastPageSize = (totalCount % pageSize == 0) ? pageSize : (totalCount % pageSize);

        for (int page = 0; page < totalPage; page++) {
            if (page == totalPage - 1) {
                param.put("pageNum", lastPageSize);
            } else {
                param.put("pageNum", pageSize);
            }
            param.put("start", page * pageSize);
            List<PayPlanEntityExt> payPlanEntityDBList = payPlanModel.findEntitys(param);
            if (payPlanEntityDBList.isEmpty()) {
                continue;
            }
            List<Long> purchaseIdIn = new ArrayList<>();
            List<Long> payPlanIdIn = new ArrayList<>();
            Map<Long, Long> payPlan2PurchaseMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            for (PayPlanEntityExt payPlanEntityExt : payPlanEntityDBList) {
                Long purchaseId = null;
                try {
                    purchaseId = payPlanEntityExt.getData().getLong(PayPlanEnum.LINK_PURCHASE.getAttr());
                } catch (Exception e) {
                }
                if (purchaseId != null) {
                    payPlan2PurchaseMap.put(payPlanEntityExt.getId(), purchaseId);
                    purchaseIdIn.add(purchaseId);
                }
                payPlanIdIn.add(payPlanEntityExt.getId());
            }
            param.remove("pageNum");
            param.remove("purchaseIdIn");
            param.put("payPlanIdIn", payPlanIdIn);
            List<PayPlanUserEntity> payPlanUserEntityList = payPlanUserModel.findEntitys(param);
            param.remove("payPlanIdIn");
            param.put("purchaseIdIn", purchaseIdIn);
            List<PurchaseUserEntity> purchaseUserEntityList = purchaseUserModel.findEntitys(param);
            Map<Long, List<PurchaseUserEntity>> purchaseUserMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            purchaseUserEntityList.forEach(purchaseUserEntity -> {
                List<PurchaseUserEntity> userEntityList = new ArrayList<>();
                if (purchaseUserMap.containsKey(purchaseUserEntity.getDataId())) {
                    userEntityList = purchaseUserMap.get(purchaseUserEntity.getDataId());
                }
                userEntityList.add(purchaseUserEntity);
                purchaseUserMap.put(purchaseUserEntity.getDataId(), userEntityList);
            });
            List<PayPlanUserEntity> insertPayPlanUserEntityList = new ArrayList<>();
            payPlan2PurchaseMap.entrySet().forEach(entry -> {
                if (CollectionUtils.isNotEmpty(purchaseUserMap.get(entry.getValue()))) {
                    for (PurchaseUserEntity purchaseUserEntity : purchaseUserMap.get(entry.getValue())) {
                        PayPlanUserEntity payPlanUserEntity = new PayPlanUserEntity();
                        BeanUtil.copyProperties(purchaseUserEntity, payPlanUserEntity);
                        payPlanUserEntity.setId(null);
                        payPlanUserEntity.setDataId(entry.getKey());
                        payPlanUserEntity.setPurchaseId(purchaseUserEntity.getDataId());
                        insertPayPlanUserEntityList.add(payPlanUserEntity);
                    }
                }
            });
            if (CollectionUtils.isNotEmpty(payPlanUserEntityList)) {
                payPlanUserModel.batchDelete(fixDataJobDTO.getCorpid(), payPlanUserEntityList);
            }
            if (CollectionUtils.isNotEmpty(insertPayPlanUserEntityList)) {
                payPlanUserModel.insertBatch(insertPayPlanUserEntityList);
            }
        }
        LOG.warn("操作成功");
        return null;
    }

    @RequestMapping(value = "/fixRepeatCustomer", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String fixRepeatCustomer(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        BoolQueryBuilder boolQueryBuilder = boolQuery();
        boolQueryBuilder.filter(termQuery(ParameterConstant.CORPID, fixDataJobDTO.getCorpid()));
        boolQueryBuilder.filter(termQuery(ParameterConstant.DEL, DelEnum.NORMAL.getDel()));
        boolQueryBuilder.filter(termQuery(CustomerManagementEnum.getAttrConnectData(CustomerManagementEnum.IS_PUBLIC), 1));
        boolQueryBuilder.filter(rangeQuery(FieldTypeEnum.ADDTIME.getAlias()).gte(DateTimeUtil.getTodayInt() - 86400L).lt(DateTimeUtil.getTodayInt()));
        List<String> fieldList = new ArrayList<>();
        fieldList.add("data." + CustomerManagementEnum.PHONE.getAttr() + StringConstant.POINT + StringConstant.PHONE_TEL_ATTR);
        fieldList.add(FieldTypeEnum.DATAID.getAlias());
        IndexTypeEnum customerIndex = indexTypeModel.getCustomerIndex(fixDataJobDTO.getCorpid(), XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode(), SaasMarkEnum.SAAS.getCode());
        List<PaasFormDataEntity> customerList = esHelper.findByScroll(customerIndex, boolQueryBuilder, PaasFormDataEntity.class, fieldList);
        LOG.warn("该公司在es中共有" + customerList.size() + "条数据");
        Map<String, List<Long>> phoneMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (PaasFormDataEntity paasFormDataEntity : customerList) {
            JSONArray phoneArr = null;
            if (Objects.nonNull(paasFormDataEntity.getData())) {
                phoneArr = paasFormDataEntity.getData().getJSONArray(CustomerManagementEnum.PHONE.getAttr());
            }
            if (Objects.nonNull(phoneArr)) {
                for (int i = 0; i < phoneArr.size(); i++) {
                    JSONObject phoneObj = phoneArr.getJSONObject(i);
                    String phone = phoneObj.getString(StringConstant.PHONE_TEL_ATTR);
                    if (StringUtil.isNotEmpty(phoneObj.getString(StringConstant.PHONE_TEL_ATTR))) {
                        List<Long> dataIdIn = new ArrayList<>();
                        if (phoneMap.containsKey(phone)) {
                            dataIdIn = phoneMap.get(phone);
                        }
                        dataIdIn.add(paasFormDataEntity.getDataId());
                        phoneMap.put(phone, dataIdIn);
                    }
                }
            }
        }
        List<Long> delEntityList = new ArrayList<>();
        phoneMap.entrySet().forEach(entry -> {
            if (entry.getValue().size() > 1) {
                List<Long> list = entry.getValue();
                list.remove(0);
                delEntityList.addAll(list);
            }
        });
        if (CollectionUtils.isNotEmpty(delEntityList)) {
            customerModel.thoroughDeleteBatch(delEntityList, fixDataJobDTO.getCorpid(), DelEnum.REMOVE_COMPLETELY.getDel());
        }
        LOG.warn("操作成功");
        return null;
    }

    @RequestMapping(value = "/fixPaidPayment", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String fixPaidPayment(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        List<String> corpidList = fixDataJobDTO.getCorpidList();
        for (String corpid : corpidList) {
            Long dataDataMark = 0L;
            List<PaasFormDataEntityExt> paasFormDataEntityExtList = new ArrayList<>();
            paasFormDataEntityExtList.add(new PaasFormDataEntityExt());
            while (!paasFormDataEntityExtList.isEmpty()) {
                BoolQueryBuilder boolQueryBuilder = boolQuery();
                boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
                if (Objects.nonNull(fixDataJobDTO.getDataId())) {
                    boolQueryBuilder.filter(termQuery(FieldTypeEnum.DATAID.getAlias(), fixDataJobDTO.getDataId()));
                }
                boolQueryBuilder.mustNot(termQuery(PaymentEnum.getEsAttr4Keyword(PaymentEnum.IS_RED), 1));
                boolQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
                ListVO listVO = scriptEsHelper.list(boolQueryBuilder, 100, PaasFormDataEntityExt.class, IndexTypeEnum.IDX_SAAS_PAYMENT, dataDataMark);
                paasFormDataEntityExtList = listVO.getList();
                dataDataMark = listVO.getDataIdMark();
                if (paasFormDataEntityExtList.isEmpty()) {
                    continue;
                }
                List<Long> paymentIdList = new ArrayList<>(100);
                for (PaasFormDataEntityExt entityExt : paasFormDataEntityExtList) {
                    paymentIdList.add(entityExt.getDataId());
                }
                boolQueryBuilder = boolQuery();
                boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
                boolQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
                boolQueryBuilder.filter(termsQuery(PaymentSheetEnum.getEsAttr4Keyword(PaymentSheetEnum.PAYMENT), paymentIdList));
                List<PaasFormDataEntityExt> paymentSheetList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_PAYMENT_SHEET, boolQueryBuilder, PaasFormDataEntityExt.class, null);
                Map<Long, Double> amountMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                Set<Long> badSet = new HashSet<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                for (PaasFormDataEntityExt entityExt : paymentSheetList) {
                    Long paymentId = entityExt.getData().getLong(PaymentSheetEnum.PAYMENT.getAttr());
                    Integer isBad = entityExt.getData().getInteger(PaymentSheetEnum.IS_BAD.getAttr());
                    if (Objects.equals(isBad, IsBadEnum.IS_BAD.getCode())) {
                        badSet.add(paymentId);
                        continue;
                    }
                    Double paymentAmount = entityExt.getData().getDouble(PaymentSheetEnum.AMOUNT.getAttr());
                    Double amount = amountMap.getOrDefault(paymentId, 0D);
                    amount += paymentAmount;
                    amountMap.put(paymentId, amount);
                }
                List<UpdateDataEntity> updateDataEntityList = new ArrayList<>();
                List<Long> sucessList = new LinkedList<>();
                for (PaasFormDataEntityExt entityExt : paasFormDataEntityExtList) {
                    JSONObject data = entityExt.getData();
                    Long paymentId = entityExt.getDataId();
                    Double amount = data.getDouble(PaymentEnum.AMOUNT.getAttr());
                    Double realAmount = data.getDouble(PaymentEnum.REAL_AMOUNT.getAttr());
                    Double unAmount = data.getDouble(PaymentEnum.UN_AMOUNT.getAttr());
                    String status = data.getString(PaymentEnum.STATUS.getAttr());

                    Double sheetAmount = amountMap.getOrDefault(paymentId, 0D);
                    Boolean isBad = badSet.contains(paymentId);

                    //回款状态
                    //已收未收
                    //坏账
                    Double tempRealAmount = sheetAmount;
                    Double tempUnAmount = amount - sheetAmount;
                    String tempStatus;
                    if (Objects.equals(amount, tempRealAmount)) {
                        tempStatus = PaymentStatusEnum.RECEIVABLES.getCode();
                    } else if (tempRealAmount == 0D) {
                        if (isBad) {
                            tempStatus = PaymentStatusEnum.BAD_DEBT.getCode();
                        } else {
                            tempStatus = PaymentStatusEnum.UN_RECEIVABLES.getCode();
                        }
                    } else {
                        if (isBad) {
                            tempStatus = PaymentStatusEnum.PARTIAL_BAD_DEBT.getCode();
                        } else {
                            tempStatus = PaymentStatusEnum.PARTIAL_RECEIPTS.getCode();
                        }
                    }
                    JSONObject updateData = new JSONObject();
                    //if (!Objects.equals(realAmount, tempRealAmount)) {
                        updateData.put(PaymentEnum.REAL_AMOUNT.getAttr(), tempRealAmount);
                    //}
                    //if (!Objects.equals(unAmount, tempUnAmount)) {
                        updateData.put(PaymentEnum.UN_AMOUNT.getAttr(), tempUnAmount);
                    //}
                   // if (!Objects.equals(status, tempStatus)) {
                        updateData.put(PaymentEnum.STATUS.getAttr(), tempStatus);
                    //}
                    if (!updateData.isEmpty()) {
                        sucessList.add(paymentId);
                        updateDataEntityList.add(ExplainUtil.getUpdateData(paymentId, updateData, corpid));
                    }
                }
                if (!updateDataEntityList.isEmpty()) {
                    paymentModel.updateBatch(updateDataEntityList, corpid);
                    LOG.warn("fixPaidPayment:" + JSONArray.toJSONString(sucessList));
                }
            }
        }
        LOG.warn("fixPaidPayment over");
        return null;
    }


    @RequestMapping(value = "/fixUnPaidOverDue", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String fixUnPaidOverDue(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006);
        }

        //遍历出有自定义的公司
        // 因为人员在不同公司的user_id可以一样，所以这边只能用循环所有公司来处理
        Map<String, Object> companyParam = new HashMap<String, Object>(16){{
            put("del", 0);
            put("defaultGroupCode", ListGroupEnum.UNPAID.getCode());
            put("groupByStr","corpid");
        }};

        List<PaasListGroupEntity> companyList = paasListGroupModel.list(companyParam);
        int count = 1;
        int corpidSize = companyList.size();
        LOG.info("开始刷脚本："+corpidSize);
        for (int index = 0; index < corpidSize; index++ ){
            String corpid = companyList.get(index).getCorpid();
            //查询出已经有逾期未付款分组的客户
            Map<String, Object> existedParam = new HashMap<String, Object>(16){{
                put("del", 0);
                put("defaultGroupCode", ListGroupEnum.UNPAID_OVERDUE.getCode());
                put("corpid", corpid);
                put("groupByStr","creator_id");
            }};

            List<PaasListGroupEntity> listGroupExistedList= paasListGroupModel.list(existedParam);
            List<String> creatorIds = new ArrayList<>();
            listGroupExistedList.forEach(item->{
                if (!item.getCreatorId().isEmpty()){
                    creatorIds.add(item.getCreatorId());
                }
            });

            //查询出这家公司保存的全部未付款分组
            Map<String, Object> param = new HashMap<String, Object>(16){{
                put("del", 0);
                put("defaultGroupCode", ListGroupEnum.UNPAID.getCode());
                put("corpid", corpid);
                put("groupByStr","creator_id");
            }};

            List<PaasListGroupEntity> listGroupList= paasListGroupModel.list(param);

            //遍历
            List<PaasListGroupEntity> insertList = new ArrayList<>();
            listGroupList.forEach(item->{
                if (!creatorIds.contains(item.getCreatorId())){
                    insertList.add(new PaasListGroupEntity(){{
                        long now = DateUtil.getInt();
                        BeanUtil.copyProperties(item, this);
                        setId(null);
                        setAddTime(now);
                        setUpdateTime(now);
                        setName(ListGroupEnum.UNPAID_OVERDUE.getName());
                        setDefaultGroupCode(ListGroupEnum.UNPAID_OVERDUE.getCode());
                        setSort(5);
                        setJsonData("[]");
                    }});
                }
            });
            if (!insertList.isEmpty()) {
                paasListGroupModel.insertBatch(insertList);
                LOG.info("批量添加逾期未付款数据库数据-----corpid=" + corpid + "----------数量为" + insertList.size());
            }
            LOG.info("=============" + count + "/" + corpidSize);
            count++;
        }
        LOG.info("结束 fixUnPaidOverDue success");
        return null;
    }

    /**
     * 修复退货退款关联合同产品的数量
     * @param fixDataJobDTO
     * @param br
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/updateContractProduct", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String updateContractProduct(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        BoolQueryBuilder boolQueryBuilder = boolQuery();
        boolQueryBuilder.mustNot(termsQuery("corpid.keyword", Arrays.asList("ding36032abc911708fd35c2f4657eb6378f", "ding8fdcf6ee06fa01eb", "ding0167c409336f4a9735c2f4657eb6378f",
                "dingbc056cd6656b2080", "ding9ab8ee5bfe81d537")));
        boolQueryBuilder.filter(termQuery(ContractProductSubFormEnum.getEsAttr(ContractProductSubFormEnum.TYPE), 202));
        boolQueryBuilder.filter(rangeQuery(ContractProductSubFormEnum.getEsAttr(ContractProductSubFormEnum.PRODUCT_NUM)).gt(0));
        IndexTypeEnum indexTypeEnum = IndexTypeEnum.IDX_SAAS_CONTRACT_PRODUCT;
        boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD,IndexTypeEnum.IDX_SAAS_CONTRACT_PRODUCT.getType()));
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
//        sourceBuilder.fetchSource(new String[]{"id","corpid","contractId"},null);
        sourceBuilder.query(boolQueryBuilder);
        SearchRequest searchRequest = new SearchRequest(indexTypeEnum.getIndex());
        searchRequest.source(sourceBuilder);
        EsUtil.setPage(sourceBuilder, 1, SizeConstant.PAGE_SIZE);
        List<PaasFormDataEntity> list = xbbElasticsearchRestTemplate.findScrollList(PaasFormDataEntity.class, searchRequest, SizeConstant.SCROLL_TIME_IN_MILLIS);
        List<ContractProductEntity> contractProductEntities = transferSubFormHelper.transferFormDataToContractProductList(list);
        List<InsertDTO> updateList = new ArrayList<>();
        for (ContractProductEntity entity : contractProductEntities) {
            Double productNum = entity.getProductNum();
            if (productNum == null) {
                continue;
            }
            Map<String, Object> map = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            map.put("productNum", -1 * productNum);
            InsertDTO insertDTO = new InsertDTO();
            insertDTO.setWaitUntil(WriteRequest.RefreshPolicy.NONE);
            insertDTO.setEsId(entity.getCorpid() + "_" + entity.getId());
            insertDTO.setParent(entity.getCorpid() + "_" + entity.getContractId());
            insertDTO.setSource(map);
            insertDTO.setIndexTypeEnum(indexTypeEnum);
            updateList.add(insertDTO);
        }
        paasEsModelImpl.updateBatch(updateList, WriteRequest.RefreshPolicy.NONE);
        LOG.warn("============更新完毕" + list.size() + "==" + updateList.size());
        return "";
    }


    @RequestMapping(value = "/fixPurchaseAllInComing", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String fixPurchaseAllInComing(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        List<String> corpidList = fixDataJobDTO.getCorpidList();
        Integer total = corpidList.size();
        Integer index = 1;
        for (String corpid : corpidList) {
            Long dataDataMark = 0L;
            List<PaasFormDataEntityExt> paasFormDataEntityExtList = new ArrayList<>();
            paasFormDataEntityExtList.add(new PaasFormDataEntityExt());
            while (!paasFormDataEntityExtList.isEmpty()) {
                BoolQueryBuilder boolQueryBuilder = boolQuery();
                boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
                boolQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
                ListVO listVO = scriptEsHelper.list(boolQueryBuilder, 100, PaasFormDataEntityExt.class, IndexTypeEnum.IDX_SAAS_PURCHASE, dataDataMark, Arrays.asList(FieldTypeEnum.DATAID.getAlias(), PurchaseEnum.ALL_INCOMING.getAttr()));
                dataDataMark = listVO.getDataIdMark();
                paasFormDataEntityExtList = listVO.getList();
//                LOG.warn("fixPurchaseAllInComing：" + index + "/" + total);
//                index++;
//                BoolQueryBuilder boolQueryBuilder = boolQuery();
//                boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
//                boolQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
//                List<PaasFormDataEntityExt> paasFormDataEntityExtList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_PURCHASE, boolQueryBuilder, PaasFormDataEntityExt.class, Arrays.asList(FieldTypeEnum.DATAID.getAlias(), PurchaseEnum.getAttrConnectData(PurchaseEnum.ALL_INCOMING)));
                List<UpdateDataEntity> updateDataEntityList = new ArrayList<>();
                for (PaasFormDataEntityExt entityExt : paasFormDataEntityExtList) {
                    JSONObject data = entityExt.getData();
                    Integer allInComing = Objects.isNull(data) ? null : data.getInteger(PurchaseEnum.ALL_INCOMING.getAttr());
                    Boolean flag = purchaseService.judgePurchaseAllInBound(0L, entityExt.getDataId(), corpid, new ArrayList<>());
                    if (Objects.isNull(data)) {
                        JSONObject json = new JSONObject();
                        json.put(PurchaseEnum.ALL_INCOMING.getAttr(), flag ? 1 : 0);
                        updateDataEntityList.add(ExplainUtil.getUpdateData(entityExt.getDataId(), json, corpid));
                        LOG.warn("fixPurchaseAllInComing:" + entityExt.getDataId() + ":" + null + "-->" + (flag ? 1 : 0));
                    } else if ((Objects.equals(allInComing, AllInBoundEnum.ALL_IN.getCode())) ^ flag) {
                        JSONObject json = new JSONObject();
                        json.put(PurchaseEnum.ALL_INCOMING.getAttr(), flag ? 1 : 0);
                        updateDataEntityList.add(ExplainUtil.getUpdateData(entityExt.getDataId(), json, corpid));
                        LOG.warn("fixPurchaseAllInComing:" + entityExt.getDataId() + ":" + allInComing + "-->" + (flag ? 1 : 0));
                    }
                }
                if (!updateDataEntityList.isEmpty()) {
                    purchaseModel.updateBatch(updateDataEntityList, corpid);
                }
            }
        }
        LOG.warn("fixPurchaseAllInComing over");
        return null;
    }

    @RequestMapping(value = "/fixContractFinishAmout", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String fixContractFinishAmout(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        Long contractId = fixDataJobDTO.getDataId();
        String corpid = fixDataJobDTO.getCorpid();
        ContractEntityExt contract = contractModel.getByKey(contractId, corpid);
        if (contract == null) {
            return "合同不存在或已删除";
        }
        FormDataUpdateGetDTO formDataUpdateGetDTO = new FormDataUpdateGetDTO();
        BeanUtil.copyProperties(fixDataJobDTO, formDataUpdateGetDTO);
        fundFixDataService.fixContractAmount(formDataUpdateGetDTO, contractId, corpid, contract);
        LOG.warn("fixContractFinishAmout over");
        return null;
    }

    @RequestMapping(value = "/fixContractFinishAmout/batch", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String fixContractFinishAmoutBatch(@RequestBody @Valid FixDataJobBatchDTO fixDataJobBatchDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobBatchDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        List<Long> dataIdList = fixDataJobBatchDTO.getDataIdList();
        if (dataIdList != null && dataIdList.size() > PageConstant.CALL_CENTER_DU_YAN_CALL_LOG_MAX_PAGE_SIZE) {
            return "最多一次性执行" + PageConstant.CALL_CENTER_DU_YAN_CALL_LOG_MAX_PAGE_SIZE + "条数据";
        }
        String corpid = fixDataJobBatchDTO.getCorpid();
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put("corpid", corpid);
        CommentUtil.addToMap(param, "idIn", dataIdList);
        param.put("del", 0);
        Integer total = contractModel.getEntitysCount(param);
        Integer start = 0;
        //每次查询100条
        Integer pageNum = 100;
        Long idGte = 0L;
        param.put("start", start);
        param.put("pageNum", pageNum);
        param.put("orderByStr", "id asc");
        int dealCount = 0;
        while (true) {
            param.put("idGte", idGte);
            List<ContractEntityExt> list  = contractModel.findEntitys(param);
            dealCount += list.size();
            if (list.size() == 0) {
                break;
            }
            idGte = list.get(list.size() - 1).getId();
            FormDataUpdateGetDTO formDataUpdateGetDTO = new FormDataUpdateGetDTO();
            BeanUtil.copyProperties(fixDataJobBatchDTO, formDataUpdateGetDTO);
            for (ContractEntityExt contract : list) {
                formDataUpdateGetDTO.setDataId(contract.getId());
                fundFixDataService.fixContractAmount(formDataUpdateGetDTO, contract.getId(), corpid, contract);
            }
            LOG.warn("处理进度：已处理" + dealCount + "/" + total);
        }
        LOG.warn("fixContractFinishAmoutBatch over");
        return null;
    }

    @RequestMapping(value = "/fixBalanceCustomer", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String fixBalanceCustomer(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        Long customerId = fixDataJobDTO.getDataId();
        if (customerId == null) {
            return "dataId参数不能为空";
        }
        String corpid = fixDataJobDTO.getCorpid();
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put("corpid", corpid);
        param.put("del", 0);
        param.put("flowStatusIn", Arrays.asList(FlowStatusEnum.NOT_NEED_APPROVAL.getType(), FlowStatusEnum.PASS.getType()));
        param.put("customerId", customerId);
        /**
         只查询预收款，预收款核销，红冲预收款余额
         预收款：预收款余额增加
         预收款核销，红冲预收款余额：预收款余额较少
         */
        String codePrepayment = PaymentSheetTypeEnum.PREPAYMENT.getCode();
        String codeWriteOffPrepayment = PaymentSheetTypeEnum.WRITE_OFF_PREPAYMENT.getCode();
        String codeRedPrepayment = PaymentSheetTypeEnum.RED_PREPAYMENT.getCode();
        String codeRedWriteOffBalance = PaymentSheetTypeEnum.RED_WRITE_OFF_BALANCE.getCode();
        List<String> sheetTypeIn = Arrays.asList(codePrepayment, codeWriteOffPrepayment, codeRedPrepayment, codeRedWriteOffBalance);
        param.put("sheetTypeIn", sheetTypeIn);
        List<PaymentSheetEntityExt> sheetList = paymentSheetModel.findEntitys(param);
        //该客户的预收余额
        Double balance = 0D;
        for (PaymentSheetEntityExt entityExt : sheetList) {
            JSONObject data = JsonHelperUtil.getJSONObject(entityExt.getData());
            String sheetType = data.getString(PaymentSheetEnum.PAYMENT_SHEET_TYPE.getAttr());
            Double amount = 0D;
            if (Objects.equals(codePrepayment, sheetType) || Objects.equals(codeRedPrepayment, sheetType)) {
                //预收款：预收款余额增加
                //红冲预收款余额(本身就是负数)：预收款余额较少
                amount = data.getDoubleValue(PaymentSheetEnum.AMOUNT.getAttr());
            } else if (Objects.equals(codeWriteOffPrepayment, sheetType) || Objects.equals(codeRedWriteOffBalance, sheetType)) {
                //预收款核销，红冲预收款余额：预收款余额较少
                //红冲预收款核销(退到余额) - 本身是负数，再取反：预收款余额增加
                amount = Arith.mul(data.getDoubleValue(PaymentSheetEnum.WRITE_OFF_AMOUNT.getAttr()), -1D);
            }
            balance = Arith.add(balance, amount);
        }
        //该客户的预收款余额实体
        PaymentBalanceEntity paymentBalanceEntity = paymentBalanceModel.getByCustomerId(customerId, corpid);
        if (paymentBalanceEntity == null && Objects.equals(0D, balance)) {
            //不用处理
            return "处理完毕";
        } else if (balance < 0) {
            return "该客户总预余额小于0，不能处理";
        } else if (paymentBalanceEntity == null) {
            return "该客户没有预收余额，不用处理";
        }
        paymentBalanceEntity.setAdvancePaymentBalance(balance);
        paymentBalanceEntity.setDel(0);
        paymentBalanceModel.updatePaymentBalanceById(paymentBalanceEntity);
        LOG.warn("fixBalanceCustomer over");
        return "客户余额处理完毕";
    }

    @RequestMapping(value = "/fixPaymentFinishAmout", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String fixPaymentFinishAmout(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        Long paymentId = fixDataJobDTO.getDataId();
        String corpid = fixDataJobDTO.getCorpid();
        PaymentEntityExt payment = paymentModel.getByKey(paymentId, corpid);
        if (payment == null) {
            return "应收款不存在或已删除";
        }
        FormDataUpdateGetDTO formDataUpdateGetDTO = new FormDataUpdateGetDTO();
        BeanUtil.copyProperties(fixDataJobDTO, formDataUpdateGetDTO);
        fundFixDataService.fixPaymentAmount(formDataUpdateGetDTO, paymentId, corpid, payment);
        LOG.warn("fixPaymentFinishAmout over");
        return null;
    }

    @RequestMapping(value = "/fixPaymentFinishAmout/batch", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String fixPaymentFinishAmoutBatch(@RequestBody @Valid FixDataJobBatchDTO fixDataJobBatchDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobBatchDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        List<Long> dataIdList = fixDataJobBatchDTO.getDataIdList();
        if (dataIdList != null && dataIdList.size() > PageConstant.CALL_CENTER_DU_YAN_CALL_LOG_MAX_PAGE_SIZE) {
            return "最多一次性执行" + PageConstant.CALL_CENTER_DU_YAN_CALL_LOG_MAX_PAGE_SIZE + "条数据";
        }
        String corpid = fixDataJobBatchDTO.getCorpid();
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put("corpid", corpid);
        CommentUtil.addToMap(param, "idIn", dataIdList);
        param.put("del", 0);
        Integer total = paymentModel.getEntitysCount(param);
        Integer start = 0;
        //每次查询100条
        Integer pageNum = 100;
        Long idGte = 0L;
        param.put("start", start);
        param.put("pageNum", pageNum);
        param.put("orderByStr", "id asc");
        int dealCount = 0;
        while (true) {
            param.put("idGte", idGte);
            List<PaymentEntityExt> list  = paymentModel.findEntitys(param);
            dealCount += list.size();
            if (list.size() == 0) {
                break;
            }
            idGte = list.get(list.size() - 1).getId();
            FormDataUpdateGetDTO formDataUpdateGetDTO = new FormDataUpdateGetDTO();
            BeanUtil.copyProperties(fixDataJobBatchDTO, formDataUpdateGetDTO);
            for (PaymentEntityExt payment : list) {
                formDataUpdateGetDTO.setDataId(payment.getId());
                fundFixDataService.fixPaymentAmount(formDataUpdateGetDTO, payment.getId(), corpid, payment);
            }
            LOG.warn("处理进度：已处理" + dealCount + "/" + total);
        }
        LOG.warn("fixPaymentFinishAmout over");
        return null;
    }

    /**
     * 修复格润之前数据迁移所造成的红冲回款单数据，bug：20210
     * @param fixDataJobDTO
     * @param br
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/updateRedPayment", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String updateRedPayment(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006);
        }
        String corpid = "ding9ab8ee5bfe81d537";
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        BoolQueryBuilder boolQueryBuilder = boolQuery();
        boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
        boolQueryBuilder.filter(termQuery(PaymentEnum.getEsAttr4Keyword(PaymentEnum.IS_RED), BasicConstant.ONE));
        boolQueryBuilder.filter(termQuery("del", 0));
        boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD,IndexTypeEnum.IDX_SAAS_PAYMENT.getType()));
        sourceBuilder.query(boolQueryBuilder);
        SearchRequest searchRequest = new SearchRequest(IndexTypeEnum.IDX_SAAS_PAYMENT.getIndex());
        searchRequest.source(sourceBuilder);
        EsUtil.setPage(sourceBuilder, 1, SizeConstant.PAGE_SIZE);
        List<PaymentEntityExt> paymentList = xbbElasticsearchRestTemplate.findScrollList(PaymentEntityExt.class, searchRequest, SizeConstant.SCROLL_TIME_IN_MILLIS);
        List<UpdateDataEntity> updateDataEntityList = new ArrayList<>();
        for (PaymentEntityExt paymentExt : paymentList) {
            JSONObject data = paymentExt.getData();
            Double unAmount = data.getDouble(PaymentEnum.UN_AMOUNT.getAttr());
            String status = data.getString(PaymentEnum.STATUS.getAttr());
            if (!Objects.equals(unAmount, BasicConstant.ZERO)) {
                JSONObject json = new JSONObject();
                json.put(PaymentEnum.UN_AMOUNT.getAttr(), BasicConstant.ZERO);
                updateDataEntityList.add(ExplainUtil.getUpdateData(paymentExt.getDataId(), json, corpid));
            }
//            if(!Objects.equals(status, PaymentStatusEnum.REFUNDED.getCode())){
//                JSONObject json = new JSONObject();
//                json.put(PaymentEnum.STATUS.getAttr(), PaymentStatusEnum.REFUNDED.getCode());
//                updateDataEntityList.add(ExplainUtil.getUpdateData(paymentExt.getDataId(), json, corpid));
//            }
        }
        if (!updateDataEntityList.isEmpty()) {
            paymentModel.updateBatch(updateDataEntityList, corpid);
        }
        LOG.warn("updateRedPayment over");
        return "";
    }

    @RequestMapping(value = "/fixContractTeamAddCusId", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String fixContractTeamAddCusId(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        List<String> corpidList = companyModel.getCorpidList();
        int index = 1;
        for (String corpid : corpidList) {
            LOG.warn("fixContractUser:" + index + "/" + corpidList.size());
            index++;
            Long dataDataMark = 0L;
            List<PaasFormDataEntityExt> paasFormDataEntityExtList = new ArrayList<>();
            paasFormDataEntityExtList.add(new PaasFormDataEntityExt());
            while (!paasFormDataEntityExtList.isEmpty()) {
                BoolQueryBuilder boolQueryBuilder = boolQuery();
                boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
//                boolQueryBuilder.filter(boolQuery().mustNot(existsQuery("customerId")));
                boolQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
                ListVO listVO = scriptEsHelper.list(boolQueryBuilder, 100, PaasFormDataEntityExt.class, IndexTypeEnum.IDX_SAAS_CONTRACT, dataDataMark);
                paasFormDataEntityExtList = listVO.getList();
                dataDataMark = listVO.getDataIdMark();
                if (paasFormDataEntityExtList.isEmpty()) {
                    continue;
                }
                List<Long> dataIdList = new ArrayList<>();
                Map<Long, Long> customerMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                paasFormDataEntityExtList.forEach(item -> {
                    dataIdList.add(item.getDataId());
                    customerMap.put(item.getDataId(), item.getData().getLong(ContractEnum.LINK_CUSTOMER.getAttr()));
                });
                boolQueryBuilder = boolQuery();
                boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
                boolQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
                boolQueryBuilder.filter(termsQuery(ContractTeamEnum.getEsAttr(ContractTeamEnum.DATA_ID), dataIdList));
                boolQueryBuilder.filter(boolQuery().mustNot(existsQuery(ContractTeamEnum.getAttrConnectData(ContractTeamEnum.CUSTOMER_ID))));
                List<PaasFormDataEntity> contractUserEntityList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_CONTRACT_TEAM, boolQueryBuilder, PaasFormDataEntity.class, null);


                if (contractUserEntityList.isEmpty()) {
                    continue;
                }
                List<ContractUserEntity> userTeamEntities = (List<ContractUserEntity>) transferSubFormHelper.transferFormDataToUserTeamList(IndexTypeEnum.IDX_SAAS_CONTRACT_TEAM, contractUserEntityList);
                for (ContractUserEntity entity : userTeamEntities) {
                    entity.setCustomerId(customerMap.get(entity.getDataId()));
                }
                contractUserModel.updateBatchCustomerId(userTeamEntities, corpid);
            }
        }
        LOG.warn("fixContractUser over");
        return null;
    }

    @RequestMapping(value = "/fixOpportunityTeamAddCusId", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String fixOpportunityTeamAddCusId(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        List<String> corpidList = companyModel.getCorpidList();
        int index = 1;
        for (String corpid : corpidList) {
            LOG.warn("fixOpportuntiyUser:" + index + "/" + corpidList.size());
            index++;
            Long dataDataMark = 0L;
            List<PaasFormDataEntityExt> paasFormDataEntityExtList = new ArrayList<>();
            paasFormDataEntityExtList.add(new PaasFormDataEntityExt());
            while (!paasFormDataEntityExtList.isEmpty()) {
                BoolQueryBuilder boolQueryBuilder = boolQuery();
                boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
//                boolQueryBuilder.filter(boolQuery().mustNot(existsQuery("customerId")));
                boolQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
                ListVO listVO = scriptEsHelper.list(boolQueryBuilder, 100, PaasFormDataEntityExt.class, IndexTypeEnum.IDX_SAAS_OPPORTUNITY, dataDataMark);
                paasFormDataEntityExtList = listVO.getList();
                dataDataMark = listVO.getDataIdMark();
                if (paasFormDataEntityExtList.isEmpty()) {
                    continue;
                }
                List<Long> dataIdList = new ArrayList<>();
                Map<Long, Long> customerMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                paasFormDataEntityExtList.forEach(item -> {
                    dataIdList.add(item.getDataId());
                    customerMap.put(item.getDataId(), item.getData().getLong(SalesOpportunityEnum.CUSTOMER_NAME.getAttr()));
                });
                boolQueryBuilder = boolQuery();
                boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
                boolQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
                boolQueryBuilder.filter(termsQuery(OpportunityTeamEnum.getEsAttr(OpportunityTeamEnum.DATA_ID), dataIdList));
                boolQueryBuilder.filter(boolQuery().mustNot(existsQuery(OpportunityTeamEnum.getAttrConnectData(OpportunityTeamEnum.CUSTOMER_ID))));
                List<PaasFormDataEntity> opportunityUserEntityList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_OPPORTUNITY_TEAM, boolQueryBuilder, PaasFormDataEntity.class, null);
                if (opportunityUserEntityList.isEmpty()) {
                    continue;
                }
                List<OpportunityUserEntity> userTeamEntities = (List<OpportunityUserEntity>) transferSubFormHelper.transferFormDataToUserTeamList(IndexTypeEnum.IDX_SAAS_OPPORTUNITY_TEAM, opportunityUserEntityList);
                for (OpportunityUserEntity entity : userTeamEntities) {
                    entity.setCustomerId(customerMap.get(entity.getDataId()));
                }
                opportunityUserModel.updateBatchCustomerId(userTeamEntities, corpid);
            }
        }
        LOG.warn("fixOpportuntiyUser over");
        return null;
    }

    @RequestMapping(value = "/fixPaymentTeamAddCusId", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String fixPaymentTeamAddCusId(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        List<String> corpidList = companyModel.getCorpidList();
        int index = 1;
        for (String corpid : corpidList) {
            LOG.warn("fixPaymentUser:" + index + "/" + corpidList.size());
            index++;
            Long dataDataMark = 0L;
            List<PaasFormDataEntityExt> paasFormDataEntityExtList = new ArrayList<>();
            paasFormDataEntityExtList.add(new PaasFormDataEntityExt());
            while (!paasFormDataEntityExtList.isEmpty()) {
                BoolQueryBuilder boolQueryBuilder = boolQuery();
                boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
//                boolQueryBuilder.filter(boolQuery().mustNot(existsQuery("customerId")));
                boolQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
                ListVO listVO = scriptEsHelper.list(boolQueryBuilder, 100, PaasFormDataEntityExt.class, IndexTypeEnum.IDX_SAAS_PAYMENT, dataDataMark);
                paasFormDataEntityExtList = listVO.getList();
                dataDataMark = listVO.getDataIdMark();
                if (paasFormDataEntityExtList.isEmpty()) {
                    continue;
                }
                List<Long> dataIdList = new ArrayList<>();
                Map<Long, Long> customerMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                Map<Long, Long> contractMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                paasFormDataEntityExtList.forEach(item -> {
                    dataIdList.add(item.getDataId());
                    customerMap.put(item.getDataId(), item.getData().getLong(PaymentEnum.CUSTOMER.getAttr()));
                    contractMap.put(item.getDataId(), item.getData().getLong(PaymentEnum.CONTRACT.getAttr()));
                });
                boolQueryBuilder = boolQuery();
                boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
                boolQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
                boolQueryBuilder.filter(termsQuery(PaymentTeamEnum.getEsAttr(PaymentTeamEnum.DATA_ID), dataIdList));
//                boolQueryBuilder.should(boolQuery().mustNot(existsQuery("customerId")));
//                boolQueryBuilder.should(boolQuery().mustNot(existsQuery("contractId")));
                boolQueryBuilder.minimumShouldMatch(MINI_MUM_SHOULD_MATCH);
                List<PaasFormDataEntity> paymentUserEntityList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_PAYMENT_TEAM, boolQueryBuilder, PaasFormDataEntity.class, null);
                if (paymentUserEntityList.isEmpty()) {
                    continue;
                }
                List<PaymentUserEntity> userTeamEntities = (List<PaymentUserEntity>) transferSubFormHelper.transferFormDataToUserTeamList(IndexTypeEnum.IDX_SAAS_PAYMENT_TEAM, paymentUserEntityList);
                for (PaymentUserEntity entity : userTeamEntities) {
                    entity.setCustomerId(customerMap.get(entity.getDataId()));
                    entity.setContractId(contractMap.get(entity.getDataId()));
                }
                paymentUserModel.updateBatchCustomerId(userTeamEntities, corpid);
            }
        }
        LOG.warn("fixPaymentUser over");
        return null;
    }
    @RequestMapping(value = "/selectProduct", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String selectProduct(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        long start = DateTimeUtil.getInt();
        LOG.warn("start:"+start);
        List<String> corpidList = fixDataJobDTO.getCorpidList();
        if (CollectionsUtil.isEmpty(corpidList)) {
            corpidList = companyModel.getCorpidList();
        }
        List<Integer> businessTypeList;
        if (Objects.nonNull(fixDataJobDTO.getBusinessType())){
            businessTypeList = Collections.singletonList(fixDataJobDTO.getBusinessType());
        }else {
            businessTypeList = Arrays.asList(201,202,301,1001,1101,1201,1301,1404,1405,1406,1407,1408,1504,1505,1506,1507,1508,1601,1701,2301,2601,2801,4700);
        }

        int index = 0;
        Map<String,List<FieldAttrEntity>> businessProductMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (Integer businessType : businessTypeList) {
            getPoroductListMap(businessType,businessProductMap);
        }
        for (String corpid : corpidList){
            index ++;
            PaasFormEntityExt productFormEntity = paasFormModel.getByBusinessType(XbbRefTypeEnum.PRODUCT.getCode(), corpid);
            if (Objects.isNull(productFormEntity)){
                productFormEntity = paasFormModel.getByBusinessTypeNoEnable(XbbRefTypeEnum.PRODUCT.getCode(), corpid);
                if (Objects.isNull(productFormEntity)) {
                    LOG.warn(corpid + ",index:" + index + "/" + corpidList.size() + ",no product explain");
                    continue;
                }
            }
            List<PaasFormExplainEntity> paasFormExplainEntityList = paasFormExplainModel.getListForUpdateProduct(corpid,businessTypeList);
            List<PaasFormExplainEntity> updateList = new ArrayList<>();
            for (PaasFormExplainEntity paasFormExplainEntity : paasFormExplainEntityList) {
                Integer businessType = paasFormExplainEntity.getBusinessType();
                List<FieldAttrEntity> explainList = JSONArray.parseArray(paasFormExplainEntity.getExplains(), FieldAttrEntity.class);
                boolean productAttrCatch = false;
                int productAttrCatchCount = 0;
                boolean otherAttrCatch = false;
                for (FieldAttrEntity entity : explainList) {
                    if (Objects.equals(FieldTypeEnum.SELECT_PRODUCT.getType(), entity.getFieldType())) {
                        String key = businessType + "_" + entity.getAttr();
                        if (!businessProductMap.containsKey(key)){
                            continue;
                        }
                        List<FieldAttrEntity> subFieldAttrList = businessProductMap.get(key);
                        for (FieldAttrEntity subFieldAttr : subFieldAttrList){
                            if (Objects.equals(subFieldAttr.getAttr(),SelectProductEnum.PRODUCT.getAttr())){
                                LinkInfoPojo linkInfoPojo = subFieldAttr.getLinkInfo();
                                linkInfoPojo.setLinkFormId(productFormEntity.getId());
                                linkInfoPojo.setLinkMenuId(productFormEntity.getMenuId());
                                linkInfoPojo.setLinkAppId(productFormEntity.getAppId());
                                subFieldAttr.setLinkInfo(linkInfoPojo);
                                break;
                            }
                        }
                        SubFormPoJo subFormPoJo = new SubFormPoJo();
                        subFormPoJo.setItems(subFieldAttrList);
                        entity.setSubForm(subFormPoJo);
                        entity.getDefaultAttr().setDefaultType(DefaultTypeEnum.CUSTOM.getAlias());
                        if (Objects.equals(businessType,XbbRefTypeEnum.BOM_BILL.getCode()) && Objects.equals(entity.getAttr(),BomBillEnum.PRODUCT.getAttr())){
                            entity.setIsSingleRow(1);
                        }else if (Objects.equals(businessType,XbbRefTypeEnum.PRODUCTION_ORDER.getCode())){
                            entity.setEditable(0);
                        }
                        productAttrCatchCount++;
                        productAttrCatch = productAttrCatchCount >= businessTypeAttrCatch(businessType);
                    } else {
                        if (Objects.equals(businessType, XbbRefTypeEnum.CONTRACT.getCode())) {
                            if (Objects.equals(entity.getAttr(), ContractEnum.PRODUCT_TOTAL.getAttr())) {
                                TempContractEnum.initProductTotal(entity);
                                otherAttrCatch = true;
                            }
                        } else if (Objects.equals(businessType, XbbRefTypeEnum.PURCHASE.getCode())) {
                            if (Objects.equals(entity.getAttr(), PurchaseEnum.PRODUCT_TOTAL.getAttr())) {
                                TempPurchaseEnum.initProductTotal(entity);
                                otherAttrCatch = true;
                            }
                        } else if (Objects.equals(businessType, XbbRefTypeEnum.SALES_OPPORTUNITY.getCode())) {
                            if (Objects.equals(entity.getAttr(), SalesOpportunityEnum.ESTIMATE_AMOUNT.getAttr())){
                                TempSalesOpportunityEnum.initEstimateAmount(entity);
                                otherAttrCatch = true;
                            }
                        } else if (Objects.equals(businessType, XbbRefTypeEnum.RETURNED_PURCHASE.getCode())) {
                            if (Objects.equals(entity.getAttr(), ReturnedPurchaseEnum.TOTAL_MONEY.getAttr())){
                                TempReturnedPurchaseEnum.initTotalMoney(entity);
                                otherAttrCatch = true;
                            }
                        } else if (Objects.equals(businessType, XbbRefTypeEnum.REFUND.getCode())) {
                            if (Objects.equals(entity.getAttr(), RefundEnum.RETURN_AMOUNT.getAttr())){
                                TempRefundEnum.initReturnAmount(entity);
                                otherAttrCatch = true;
                            }
                        } else if (Objects.equals(businessType, XbbRefTypeEnum.QUOTATION.getCode())) {
                            if (Objects.equals(entity.getAttr(), QuotationEnum.PRODUCT_TOTAL.getAttr())){
                                TempQuotationEnum.initProductTotal(entity);
                                otherAttrCatch = true;
                            }
                        } else {
                            otherAttrCatch = true;
                        }
                    }
                    if (productAttrCatch && otherAttrCatch){
                        break;
                    }
                }
                paasFormExplainEntity.setExplains(JSONArray.toJSONString(explainList));
                updateList.add(paasFormExplainEntity);
            }
            LOG.warn(corpid + ",index:" + index + "/" + corpidList.size());
            if (!updateList.isEmpty()){
                paasFormExplainModel.updateBatchExplains(updateList,corpid);
            }
        }
        LOG.warn("consume:" + (DateTimeUtil.getInt() - start));
        LOG.warn("selectProduct over");
        return null;
    }

    private int businessTypeAttrCatch(int businessType) {
        XbbRefTypeEnum xbbRefTypeEnum = XbbRefTypeEnum.getByCode(businessType);
        switch (xbbRefTypeEnum){
            case ASSEMBLE:
            case BOM_BILL:
            case PRODUCTION_ORDER:
                return 2;
            default:
                return 1;
        }
    }

    private void getPoroductListMap(Integer businessType, Map<String, List<FieldAttrEntity>> businessProductMap) {
        Class clazz;
        Class tempClazz;
        XbbRefTypeEnum xbbRefTypeEnum = XbbRefTypeEnum.getByCode(businessType);
        switch (xbbRefTypeEnum) {
            case CONTRACT:
                clazz = ContractProductEnum.class;
                tempClazz = TempContractProductEnum.class;
                productPre(businessType,ContractEnum.PRODUCT.getAttr(),clazz,tempClazz,businessProductMap);
                break;
            case REFUND:
                //entity.setEditable(0);
                clazz = RefundProductEnum.class;
                tempClazz = TempRefundProductEnum.class;
                productPre(businessType,RefundEnum.PRODUCTS.getAttr(),clazz,tempClazz,businessProductMap);
                break;
            case SALES_OPPORTUNITY:
                clazz = OpportunityProductEnum.class;
                tempClazz = TempOpportunityProductEnum.class;
                productPre(businessType,SalesOpportunityEnum.PRODUCTS.getAttr(),clazz,tempClazz,businessProductMap);
                break;
            case SUPPLIER:
                clazz = SupplierProductEnum.class;
                tempClazz = TempSupplierProductEnum.class;
                productPre(businessType,SupplierEnum.PRODUCT_LIST.getAttr(),clazz,tempClazz,businessProductMap);
                break;
            case PURCHASE:
                clazz = PurchaseProductEnum.class;
                tempClazz = TempPurchaseProductEnum.class;
                productPre(businessType,PurchaseEnum.PRODUCT.getAttr(),clazz,tempClazz,businessProductMap);
                break;
            case RETURNED_PURCHASE:
                clazz = ReturnPurchaseProductEnum.class;
                tempClazz = TempReturnPurchaseProductEnum.class;
                productPre(businessType,ReturnedPurchaseEnum.PRODUCTS.getAttr(),clazz,tempClazz,businessProductMap);
                break;
            case ASSEMBLE:
                clazz = AssembleInProductEnum.class;
                tempClazz = TempAssembleInProductEnum.class;
                productPre(businessType,AssembleEnum.IN_PRODUCTS.getAttr(),clazz,tempClazz,businessProductMap);
                clazz = AssembleProductEnum.class;
                tempClazz = TempAssembleProductEnum.class;
                productPre(businessType,AssembleEnum.OUT_PRODUCTS.getAttr(),clazz,tempClazz,businessProductMap);
                break;
            case INSTOCK:
            case OTHER_INSTOCK:
                clazz = InstockProductEnum.class;
                tempClazz = TempInstockProductEnum.class;
                productPre(businessType,InstockEnum.PRODUCT.getAttr(),clazz,tempClazz,businessProductMap);
                break;
            case PURCHASE_INSTOCK:
                clazz = PurchaseInstockProductEnum.class;
                tempClazz = TempPurchaseInstockProductEnum.class;
                productPre(businessType,PurchaseInstockEnum.PRODUCT.getAttr(),clazz,tempClazz,businessProductMap);
                break;
            case PRODUCTION_INSTOCK:
                clazz = ProductionInstockProductEnum.class;
                tempClazz = TempProductionInstockProductEnum.class;
                productPre(businessType,ProductionInstockEnum.PRODUCT.getAttr(),clazz,tempClazz,businessProductMap);
                break;
            case RETURNED_MATERIEL_INSTOCK:
                clazz = ReturnedMaterielInstockProductEnum.class;
                tempClazz = TempReturnedMaterielInstockProductEnum.class;
                productPre(businessType,ReturnedMaterielInstockEnum.PRODUCT.getAttr(),clazz,tempClazz,businessProductMap);
                break;
            case REFUND_INSTOCK:
                clazz = RefundInstockProductEnum.class;
                tempClazz = TempRefundInstockProductEnum.class;
                productPre(businessType,RefundInstockEnum.PRODUCT.getAttr(),clazz,tempClazz,businessProductMap);
                break;
            case OUTSTOCK:
            case OTHER_OUTSTOCK:
                clazz = OutstockProductEnum.class;
                tempClazz = TempOutstockProductEnum.class;
                productPre(businessType,OutstockEnum.PRODUCT.getAttr(),clazz,tempClazz,businessProductMap);
                break;
            case CONTRACT_OUTSTOCK:
                clazz = ContractOutstockProductEnum.class;
                tempClazz = TempContractOutstockProductEnum.class;
                productPre(businessType,ContractOutstockEnum.PRODUCT.getAttr(),clazz,tempClazz,businessProductMap);
                break;
            case RETURNED_PURCHASE_OUTSTOCK:
                clazz = ReturnedPurchaseOutstockProductEnum.class;
                tempClazz = TempReturnedPurchaseOutstockProductEnum.class;
                productPre(businessType,ReturnedPurchaseOutstockEnum.PRODUCT.getAttr(),clazz,tempClazz,businessProductMap);
                break;
            case PRODUCTION_MATERIEL_OUTSTOCK:
                clazz = ProductionMaterielOutstockProductEnum.class;
                tempClazz = TempProductionMaterielOutstockProductEnum.class;
                productPre(businessType,ProductionMaterielOutstockEnum.PRODUCT.getAttr(),clazz,tempClazz,businessProductMap);
                break;
            case WORK_ORDER_OUTSTOCK:
                clazz = WorkOrderOutstockProductEnum.class;
                tempClazz = TempWorkOrderOutstockProductEnum.class;
                productPre(businessType,WorkOrderOutstockEnum.PRODUCT.getAttr(),clazz,tempClazz,businessProductMap);
                break;
            case INVENTORY:
                clazz = InventoryProductEnum.class;
                tempClazz = TempInventoryProductEnum.class;
                productPre(businessType,InventoryEnum.PRODUCT.getAttr(),clazz,tempClazz,businessProductMap);
                break;
            case TRANSFER:
                clazz = TransferProductEnum.class;
                tempClazz = TempTransferProductEnum.class;
                productPre(businessType,TransferEnum.PRODUCTS.getAttr(),clazz,tempClazz,businessProductMap);
                break;
            case WORK_ORDER:
                clazz = WorkOrderProductEnum.class;
                tempClazz = TempWorkOrderProductEnum.class;
                productPre(businessType,WorkOrderEnum.SPARE_PARTS.getAttr(),clazz,tempClazz,businessProductMap);
                break;
            case BOM_BILL:
                clazz = BomFinishProductEnum.class;
                tempClazz = TempBomFinishProductEnum.class;
                productPre(businessType,BomBillEnum.PRODUCT.getAttr(),clazz,tempClazz,businessProductMap);
                clazz = BomMaterielProductEnum.class;
                tempClazz = TempBomMaterieProductEnum.class;
                productPre(businessType,BomBillEnum.MATERIEL.getAttr(),clazz,tempClazz,businessProductMap);
                break;
            case PRODUCTION_ORDER:
                clazz = ProductionOrderFinishProductEnum.class;
                tempClazz = TempProductionOrderFinishProductEnum.class;
                productPre(businessType,ProductionOrderEnum.PRODUCT.getAttr(),clazz,tempClazz,businessProductMap);
                clazz = ProductionOrderMaterielProductEnum.class;
                tempClazz = TempProductionOrderMaterieProductEnum.class;
                productPre(businessType,ProductionOrderEnum.MATERIEL.getAttr(),clazz,tempClazz,businessProductMap);
                break;
            case ORI_STOCK:
                clazz = OriStockProductEnum.class;
                tempClazz = TempOriStockProductEnum.class;
                productPre(businessType,OriStockEnum.PRODUCT_DETAIL.getAttr(),clazz,tempClazz,businessProductMap);
                break;
            case QUOTATION:
                clazz = QuotationProductEnum.class;
                tempClazz = TempQuotationProductEnum.class;
                productPre(businessType,QuotationEnum.PRODUCT.getAttr(),clazz,tempClazz,businessProductMap);
                break;
            default:
                break;
        }
    }

    private void productPre(Integer businessType, String attr, Class clazz, Class tempClazz, Map<String, List<FieldAttrEntity>> businessProductMap){
        XbbRefTypeEnum xbbRefTypeEnum = XbbRefTypeEnum.getByCode(businessType);
        List<FieldAttrEntity> subFieldAttrList = new ArrayList<>();
        List<String> enumAttrs = InitExplainsHelper.getBusinessEnumAttrs(clazz);
        Object[] objs = clazz.getEnumConstants();
        for (Object obj : objs) {
            FieldAttrEntity newFieldAttrEntity = InitExplainsHelper.setField(clazz, enumAttrs, obj);
            try {
                if (Objects.equals(newFieldAttrEntity.getAttr(), SelectProductEnum.PRODUCT.getAttr())) {
                    //主键字段
                    List<LinkedAttrPoJo> linkedAttrPoJoList = getLinkedAttr(xbbRefTypeEnum);
                    List<LinkedAttrPoJo> linkedShowPoJoList = getLinkedShowAttr(xbbRefTypeEnum);
                    Method method = tempClazz.getMethod("init" + newFieldAttrEntity.getSaasAttr().substring(0, 1).toUpperCase() + newFieldAttrEntity.getSaasAttr().substring(1), FieldAttrEntity.class, List.class, List.class,PaasFormEntityExt.class);
                    method.invoke(tempClazz, newFieldAttrEntity, linkedAttrPoJoList,linkedShowPoJoList, new PaasFormEntityExt());
                } else {
                    Method method = tempClazz.getMethod("init" + newFieldAttrEntity.getSaasAttr().substring(0, 1).toUpperCase() + newFieldAttrEntity.getSaasAttr().substring(1), FieldAttrEntity.class);
                    method.invoke(tempClazz, newFieldAttrEntity);
                }
            } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
                e.printStackTrace();
            }
            newFieldAttrEntity.setIsRedundant(0);
            newFieldAttrEntity.setIsForbidden(0);
            newFieldAttrEntity.setVisible(1);
            newFieldAttrEntity.setParentAttr(attr);
            subFieldAttrList.add(newFieldAttrEntity);
        }
        String key = businessType + "_" + attr;
        businessProductMap.put(key,subFieldAttrList);
    }

    @RequestMapping(value = "/selectWorkOrderProduct", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String selectWorkOrderProduct(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        long start = DateTimeUtil.getInt();
        List<String> corpidList = fixDataJobDTO.getCorpidList();
        if (CollectionsUtil.isEmpty(corpidList)) {
            corpidList = companyModel.getCorpidList();
        }
        corpidList.add("0");
        Class clazz = WorkOrderProductEnum.class;
        Class tempClazz = TempWorkOrderProductEnum.class;
        List<FieldAttrEntity> subFieldAttrList = new ArrayList<>();
        List<String> enumAttrs = InitExplainsHelper.getBusinessEnumAttrs(clazz);
        Object[] objs = clazz.getEnumConstants();
        for (Object obj : objs) {
            FieldAttrEntity newFieldAttrEntity = InitExplainsHelper.setField(clazz, enumAttrs, obj);
            try {
                if (Objects.equals(newFieldAttrEntity.getAttr(), ContractProductEnum.PRODUCT.getAttr())) {
                    //主键字段
                    List<LinkedAttrPoJo> linkedAttrPoJoList = getLinkedAttr(XbbRefTypeEnum.WORK_ORDER);
                    List<LinkedAttrPoJo> linkedShowPoJoList = getLinkedShowAttr(XbbRefTypeEnum.WORK_ORDER);
                    Method method = tempClazz.getMethod("init" + newFieldAttrEntity.getSaasAttr().substring(0, 1).toUpperCase() + newFieldAttrEntity.getSaasAttr().substring(1), FieldAttrEntity.class, List.class,List.class, PaasFormEntityExt.class);
                    method.invoke(tempClazz, newFieldAttrEntity, linkedAttrPoJoList, linkedShowPoJoList, new PaasFormEntityExt());
                } else {
                    Method method = tempClazz.getMethod("init" + newFieldAttrEntity.getSaasAttr().substring(0, 1).toUpperCase() + newFieldAttrEntity.getSaasAttr().substring(1), FieldAttrEntity.class);
                    method.invoke(tempClazz, newFieldAttrEntity);
                }
            } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
                e.printStackTrace();
            }
            newFieldAttrEntity.setIsRedundant(0);
            newFieldAttrEntity.setIsForbidden(0);
            newFieldAttrEntity.setVisible(1);
            newFieldAttrEntity.setParentAttr(WorkOrderEnum.SPARE_PARTS.getAttr());
            subFieldAttrList.add(newFieldAttrEntity);
        }
        int index = 0;
        for (String corpid : corpidList){
            PaasFormEntityExt productFormEntity = paasFormModel.getByBusinessType(XbbRefTypeEnum.PRODUCT.getCode(), corpid);
            if (Objects.isNull(productFormEntity)) {
                productFormEntity = paasFormModel.getByBusinessTypeNoEnable(XbbRefTypeEnum.PRODUCT.getCode(), corpid);
            }
            index ++;
            if (Objects.isNull(productFormEntity) && !Objects.equals(corpid,"0")){
                LOG.warn(corpid + ",index:" + index + "/" + corpidList.size() + ",no product explain");
                continue;
            }
            for (FieldAttrEntity subFieldAttr : subFieldAttrList){
                if (Objects.equals(subFieldAttr.getAttr(),SelectProductEnum.PRODUCT.getAttr())){
                    LinkInfoPojo linkInfoPojo = subFieldAttr.getLinkInfo();
                    if (Objects.nonNull(productFormEntity)){
                        linkInfoPojo.setLinkFormId(productFormEntity.getId());
                        linkInfoPojo.setLinkMenuId(productFormEntity.getMenuId());
                        linkInfoPojo.setLinkAppId(productFormEntity.getAppId());
                    }
                    subFieldAttr.setLinkInfo(linkInfoPojo);
                }
            }
            Map<String,Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put("corpid",corpid);
            param.put("del",0);
            List<WorkOrderExplainEntity> paasFormExplainEntityList = workOrderExplainModel.list(param);
            int expIndex = 0;
            List<WorkOrderExplainEntity> updateList = new ArrayList<>();
            for (WorkOrderExplainEntity paasFormExplainEntity : paasFormExplainEntityList) {
                expIndex ++;
                LOG.warn(corpid + ",index:" + index + "/" + corpidList.size() + ",explain:" + expIndex + "/" + paasFormExplainEntityList.size());
                List<FieldAttrEntity> explainList = JSONArray.parseArray(paasFormExplainEntity.getExplains(), FieldAttrEntity.class);
                for (FieldAttrEntity entity : explainList) {
                    if (Objects.equals(FieldTypeEnum.SELECT_PRODUCT.getType(), entity.getFieldType())) {
                        SubFormPoJo subFormPoJo = new SubFormPoJo();
                        subFormPoJo.setItems(subFieldAttrList);
                        entity.setSubForm(subFormPoJo);
                        entity.getDefaultAttr().setDefaultType(DefaultTypeEnum.CUSTOM.getAlias());
                        paasFormExplainEntity.setExplains(JSONArray.toJSONString(explainList));
                    }
                }
//                workOrderExplainModel.update(paasFormExplainEntity);
                updateList.add(paasFormExplainEntity);
            }
            if (!updateList.isEmpty()){
                workOrderExplainModel.updateBatchExplain(updateList,corpid);
            }
        }
        LOG.warn("consume:" + (DateTimeUtil.getInt() - start));
        LOG.warn("selectWorkOrderProduct over");
        return null;
    }

    private List<LinkedAttrPoJo> getLinkedAttr(XbbRefTypeEnum xbbRefTypeEnum) {
        List<ProductEnum> productEnumList = getProductEnumList(xbbRefTypeEnum);
        List<String> enumAttrs = InitExplainsHelper.getBusinessEnumAttrs(ProductEnum.class);
        List<LinkedAttrPoJo> linkedAttrPoJoList = new ArrayList<>();
        for (ProductEnum productEnum : productEnumList){
            FieldAttrEntity newFieldAttrEntity = InitExplainsHelper.setField(ProductEnum.class, enumAttrs,productEnum);
            try {
                Method method = TempProductEnum.class.getMethod("init" + newFieldAttrEntity.getSaasAttr().substring(0, 1).toUpperCase() + newFieldAttrEntity.getSaasAttr().substring(1),FieldAttrEntity.class);
                method.invoke(TempProductEnum.class,newFieldAttrEntity);
            } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
//                e.printStackTrace();
            }
            newFieldAttrEntity.setVisible(1);
            LinkedAttrPoJo linkedAttrPoJo = new LinkedAttrPoJo();
            BeanUtil.copyProperties(newFieldAttrEntity,linkedAttrPoJo);
            linkedAttrPoJoList.add(linkedAttrPoJo);
        }
        /*if (Objects.equals(xbbRefTypeEnum, XbbRefTypeEnum.REFUND) || Objects.equals(xbbRefTypeEnum, XbbRefTypeEnum.RETURNED_PURCHASE) || Objects.equals(xbbRefTypeEnum, XbbRefTypeEnum.RETURNED_MATERIEL_INSTOCK)) {
            LinkedAttrPoJo linkedAttrPoJo = new LinkedAttrPoJo();
            FieldAttrEntity newFieldAttrEntity = InitExplainsHelper.getNewFieldAttrEntity();
            BeanUtil.copyProperties(SelectProductEnum.SOURCE_DOC,newFieldAttrEntity);
            BeanUtil.copyProperties(newFieldAttrEntity,linkedAttrPoJo);
            linkedAttrPoJoList.add(0, linkedAttrPoJo);
        }
        InitExplainsHelper.addSpecialLinkedAttrPoJo(linkedAttrPoJoList, xbbRefTypeEnum);*/
        return linkedAttrPoJoList;
    }

    private List<ProductEnum> getProductEnumList(XbbRefTypeEnum xbbRefTypeEnum) {
        List<ProductEnum> productEnums = null;
        switch (xbbRefTypeEnum) {
            case CONTRACT:
            case SALES_OPPORTUNITY:
            case PURCHASE:
            case ASSEMBLE:
            case INSTOCK:
            case OUTSTOCK:
            case INVENTORY:
            case TRANSFER:
            case WORK_ORDER:
            case BOM_BILL:
            case PRODUCTION_ORDER:
            case ORI_STOCK:
            case QUOTATION:
                productEnums = Arrays.asList(ProductEnum.PRODUCT_IMGS, ProductEnum.NAME, ProductEnum.SERIALNO, ProductEnum.SPECIFICATION, ProductEnum.STOCK, ProductEnum.UNIT);
                break;
            case SUPPLIER:
                productEnums = Arrays.asList(ProductEnum.PRODUCT_IMGS, ProductEnum.NAME, ProductEnum.SERIALNO, ProductEnum.SPECIFICATION, ProductEnum.COST, ProductEnum.PRICE, ProductEnum.UNIT);
                break;
            case CONTRACT_OUTSTOCK:
            case PRODUCTION_MATERIEL_OUTSTOCK:
            case PRODUCTION_INSTOCK:
            case RETURNED_PURCHASE_OUTSTOCK:
            case RETURNED_PURCHASE:
            case REFUND_INSTOCK:
            case REFUND:
            case PURCHASE_INSTOCK:
            case RETURNED_MATERIEL_INSTOCK:
            case WORK_ORDER_OUTSTOCK:
            case OTHER_INSTOCK:
            case OTHER_OUTSTOCK:
                productEnums = Arrays.asList(ProductEnum.NAME, ProductEnum.SERIALNO, ProductEnum.SPECIFICATION, ProductEnum.PRODUCT_IMGS);
                break;
            default:
                break;
        }
        return productEnums;
    }

    private List<LinkedAttrPoJo> getLinkedShowAttr(XbbRefTypeEnum xbbRefTypeEnum) {
        List<ProductEnum> productEnumList = getShowProductEnumList(xbbRefTypeEnum);
        List<String> enumAttrs = InitExplainsHelper.getBusinessEnumAttrs(ProductEnum.class);
        List<LinkedAttrPoJo> linkedAttrPoJoList = new ArrayList<>();
        for (ProductEnum productEnum : productEnumList){
            FieldAttrEntity newFieldAttrEntity = InitExplainsHelper.setField(ProductEnum.class, enumAttrs,productEnum);
            try {
                Method method = TempProductEnum.class.getMethod("init" + newFieldAttrEntity.getSaasAttr().substring(0, 1).toUpperCase() + newFieldAttrEntity.getSaasAttr().substring(1),FieldAttrEntity.class);
                method.invoke(TempProductEnum.class,newFieldAttrEntity);

            } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
                e.printStackTrace();
            }
            newFieldAttrEntity.setVisible(1);
            LinkedAttrPoJo linkedAttrPoJo = new LinkedAttrPoJo();
            BeanUtil.copyProperties(newFieldAttrEntity,linkedAttrPoJo);
            linkedAttrPoJoList.add(linkedAttrPoJo);
        }
        return linkedAttrPoJoList;
    }

    private List<ProductEnum> getShowProductEnumList(XbbRefTypeEnum xbbRefTypeEnum) {
        List<ProductEnum> productEnums = null;
        switch (xbbRefTypeEnum) {
            case CONTRACT:
            case SALES_OPPORTUNITY:
            case RETURNED_PURCHASE:
            case REFUND:
            case PURCHASE:
            case ASSEMBLE:
            case INSTOCK:
            case PRODUCTION_INSTOCK:
            case PURCHASE_INSTOCK:
            case REFUND_INSTOCK:
            case OTHER_INSTOCK:
            case RETURNED_MATERIEL_INSTOCK:
            case OUTSTOCK:
            case OTHER_OUTSTOCK:
            case CONTRACT_OUTSTOCK:
            case WORK_ORDER_OUTSTOCK:
            case PRODUCTION_MATERIEL_OUTSTOCK:
            case RETURNED_PURCHASE_OUTSTOCK:
            case INVENTORY:
            case TRANSFER:
            case WORK_ORDER:
            case BOM_BILL:
            case PRODUCTION_ORDER:
            case ORI_STOCK:
            case SUPPLIER:
            case QUOTATION:
                productEnums = Arrays.asList(ProductEnum.SERIALNO, ProductEnum.SPECIFICATION, ProductEnum.BARCODE);
                break;
            default:
                break;
        }
        return productEnums;
    }

    @RequestMapping(value = "/addStockInfoToProduct", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String addStockInfoToProduct(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        List<String> corpidList = fixDataJobDTO.getCorpidList();
        if (CollectionsUtil.isEmpty(corpidList)) {
            corpidList = companyModel.getCorpidList();
        }
        LOG.warn("数据库中共有公司" + corpidList.size() + "家");
        int corpidCount = 0;
        for (String corpid : corpidList) {
            BoolQueryBuilder boolQueryBuilder = boolQuery();
            boolQueryBuilder.filter(termQuery(ParameterConstant.CORPID + StringConstant.POINT + StringConstant.KEY_WORD, corpid));
            boolQueryBuilder.filter(termQuery(ParameterConstant.DEL, DelEnum.NORMAL.getDel()));
            boolQueryBuilder.mustNot(termQuery(ProductEnum.getAttrConnectData(ProductEnum.PARENT_ID), 0));
            List<String> fieldList = new ArrayList<>();
            fieldList.add(FieldTypeEnum.DATAID.getAlias());
            fieldList.add(ProductEnum.getAttrConnectData(ProductEnum.WAREHOUSE));
            List<PaasFormDataEntity> productList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_PRODUCT, boolQueryBuilder, PaasFormDataEntity.class, fieldList);
            int totalCount = productList.size();
            LOG.warn("该公司在es中共有" + totalCount + "条数据");
            List<Long> productIdList = new ArrayList<>();
            Map<Long, PaasFormDataEntity> productMap = new HashMap<>(productList.size());
            productList.forEach(item -> {
                productIdList.add(item.getDataId());
                productMap.put(item.getDataId(), item);
            });
            int pageSize = 500;
            int totalPage = (totalCount % pageSize == 0) ? (totalCount / pageSize) : (totalCount / pageSize) + 1;
            int lastPageSize = (totalCount % pageSize == 0) ? pageSize : (totalCount % pageSize);
            int updateCount = 0;
            for (int page = 0; page < totalPage; page++) {
                int start = page * pageSize;
                int end;
                if (page == totalPage - 1) {
                    end = start + lastPageSize;
                } else {
                    end = start + pageSize;
                }
                List<Long> pageProductIdList = new ArrayList<>(productIdList.subList(start, end));
                LOG.warn("第" + page + "页开始");
                Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                param.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
                param.put(ParameterConstant.CORPID, corpid);
                param.put("warehouseChecked", 1);
                param.put("productIdIn", pageProductIdList);
                List<ProductWarehouseEntity> productWarehouseList = productWarehouseModel.findEntitysWithWarehouseChecked(param,1);
                if (productWarehouseList.isEmpty()) {
                    continue;
                }
                Map<Long, Set<Long>> warehouseIdMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                productWarehouseList.forEach(item -> {
                    Long productId = item.getProductId();
                    Long warehouseId = item.getWarehouseId();
                    if (Objects.nonNull(warehouseId) && !Objects.equals(warehouseId, 0L)) {
                        if (warehouseIdMap.containsKey(productId)) {
                            warehouseIdMap.get(productId).add(warehouseId);
                        } else {
                            Set<Long> warehouseSet = new HashSet<>();
                            warehouseSet.add(warehouseId);
                            warehouseIdMap.put(productId, warehouseSet);
                        }
                    }

                });
                List<UpdateDataEntity> updateList = new ArrayList<>();
                warehouseIdMap.forEach((key, value) -> {
                    JSONObject data = new JSONObject();
                    data.put(ProductEnum.WAREHOUSE.getAttr(), JSON.parseArray(JSON.toJSONString(value)));
                    updateList.add(ExplainUtil.getUpdateData(key, data, corpid));
                });
                if (!updateList.isEmpty()) {
                    productModel.updateBatch(updateList, corpid, WriteRequest.RefreshPolicy.NONE);
                    updateCount += updateList.size();
                }
                LOG.warn("第" + page + "页结束");
            }
            LOG.warn("共更新" + updateCount + "条产品数据");
            ++corpidCount;
            LOG.warn("公司" + corpidCount + "/" + corpidList.size());
        }
        LOG.warn("操作成功");
        return null;
    }


    @RequestMapping(value = "/fixContractDiscount", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String fixContractDiscount(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        List<String> corpidList = fixDataJobDTO.getCorpidList();
        if (Objects.isNull(corpidList) || corpidList.isEmpty()) {
            corpidList = new ArrayList<>();
            Map<String, Object> param = new HashMap<>(16);
            param.put("del", 0);
            param.put("status", 1);
            int total = companyModel.getEntitysCount(param);
            int pageSize = 1000;

            for (int i = 0; i < total; i += pageSize) {
                param.clear();
                param.put("del", 0);
                param.put("status", 1);
                param.put("start", i);
                param.put("pageNum", pageSize);
                param.put("columns", "corpid");
                List<CompanyEntity> companyEntityList = companyModel.findEntitys(param);
                List<String> corpids = new ArrayList<>(companyEntityList.size());
                companyEntityList.forEach(item -> {
                    corpids.add(item.getCorpid());
                });
                corpidList.addAll(corpids);
            }

        }
        corpidList.remove("dinga93c84f4d89688bf35c2f4657eb6378f");
        int index = 1;
        for (String corpid : corpidList) {
            Long dataDataMark = 0L;
            List<PaasFormDataEntityExt> paasFormDataEntityExtList = new ArrayList<>();
            paasFormDataEntityExtList.add(new PaasFormDataEntityExt());
            while (!paasFormDataEntityExtList.isEmpty()) {
                BoolQueryBuilder boolQueryBuilder = boolQuery();
                boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
                boolQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
                ListVO listVO = scriptEsHelper.list(boolQueryBuilder, 100, PaasFormDataEntityExt.class, IndexTypeEnum.IDX_SAAS_CONTRACT, dataDataMark);
                paasFormDataEntityExtList = listVO.getList();
                dataDataMark = listVO.getDataIdMark();
                if (paasFormDataEntityExtList.isEmpty()) {
                    continue;
                }
                List<Long> dataIdList = new ArrayList<>(100);
                for (PaasFormDataEntityExt entityExt : paasFormDataEntityExtList) {
                    if (Objects.nonNull(entityExt.getData()) && Objects.isNull(entityExt.getData().get(ContractEnum.DISCOUNT.getAttr()))) {
                        dataIdList.add(entityExt.getDataId());
                    }
                }
                if (!dataIdList.isEmpty()) {
                    proUpdateHelp.updateByIds(XbbRefTypeEnum.CONTRACT.getCode(), corpid, dataIdList, ContractEnum.DISCOUNT.getAttr(), 1);
                }
            }
            LOG.warn("fixContractDiscount------------------------" + index + "/" + corpidList.size());
            index++;
        }
        LOG.warn("fixContractDiscount SUCCESS");
        return null;
    }


    @RequestMapping(value = "/fixCustomerData", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String fixCustomerData(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        List<String> corpidList = fixDataJobDTO.getCorpidList();
        if (CollectionsUtil.isEmpty(corpidList)) {
            corpidList = companyModel.getCorpidList();
        }
        int index = 1;
        Integer businessType = fixDataJobDTO.getBusinessType();
        for (String corpid : corpidList) {
            Long dataDataMark = 0L;
            IndexTypeEnum indexTypeEnum = indexTypeModel.getIndexType(corpid, businessType, fixDataJobDTO.getSaasMark());
            List<PaasFormDataEntityExt> paasFormDataEntityExtList = new ArrayList<>();
            paasFormDataEntityExtList.add(new PaasFormDataEntityExt());
            while (!paasFormDataEntityExtList.isEmpty()) {
                BoolQueryBuilder boolQueryBuilder = boolQuery();
                boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
                boolQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
                if (Objects.nonNull(fixDataJobDTO.getFormId())) {
                    boolQueryBuilder.filter(termQuery("formId", fixDataJobDTO.getFormId()));
                }
                ListVO listVO = scriptEsHelper.list(boolQueryBuilder, 1000, PaasFormDataEntityExt.class, indexTypeEnum, dataDataMark);
                paasFormDataEntityExtList = listVO.getList();
                dataDataMark = listVO.getDataIdMark();
                if (paasFormDataEntityExtList.isEmpty()) {
                    continue;
                }
                List<Long> dataIdList = new ArrayList<>(paasFormDataEntityExtList.size());
                Map<Long, PaasFormDataEntityExt> esEntityMap = new HashMap<>(paasFormDataEntityExtList.size());
                paasFormDataEntityExtList.forEach(item -> {
                    dataIdList.add(item.getDataId());
                    esEntityMap.put(item.getDataId(), item);
                });
                List<PaasFormDataEntityExt> entitys = new ArrayList<>();
//                List<PaasFormDataEntityExt> entitys = jsonSetService.getByIdInAndDel(dataIdList, corpid, businessType, DelEnum.NORMAL.getDel());

                List<PaasFormDataEntityExt> needUpdates = new ArrayList<>();
                for (PaasFormDataEntityExt entityExt : entitys) {
                    JSONObject data = entityExt.getData();
                    Set<String> keyList = data.keySet();
                    PaasFormDataEntityExt esEntity = esEntityMap.get(entityExt.getId());
                    boolean needUpdate = false;
                    if (Objects.nonNull(esEntity)) {
                        for (Map.Entry<String, Object> entry : esEntity.getData().entrySet()) {
                            if (!keyList.contains(entry.getKey()) && Objects.nonNull(entry.getValue())) {
                                data.put(entry.getKey(), entry.getValue());
                                needUpdate = true;
                            }
                        }
                        if (needUpdate) {
                            needUpdates.add(entityExt);
                        }

                    }

                }
                if (!needUpdates.isEmpty()) {
//                    jsonSetService.updateDataBatch(businessType, corpid, needUpdates);
                }
            }
            LOG.warn("fixCustomerData------------------------" + index + "/" + corpidList.size());
            index++;
        }
        LOG.warn("操作成功");
        return null;
    }

    @RequestMapping(value = "/fixSpec", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String fixSpec(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        String corpid = fixDataJobDTO.getCorpid();
        Long dataDataMark = 0L;
        List<PaasFormDataEntityExt> paasFormDataEntityExtList = new ArrayList<>();
        paasFormDataEntityExtList.add(new PaasFormDataEntityExt());
        while (!paasFormDataEntityExtList.isEmpty()) {
            BoolQueryBuilder boolQueryBuilder = boolQuery();
            boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
            boolQueryBuilder.filter(termQuery(ProductEnum.getEsAttr4Keyword(ProductEnum.PARENT_ID), 0));
            boolQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
            ListVO listVO = scriptEsHelper.list(boolQueryBuilder, 500, PaasFormDataEntityExt.class, IndexTypeEnum.getByCode(XbbRefTypeEnum.PRODUCT.getCode()), dataDataMark);
            paasFormDataEntityExtList = listVO.getList();
            dataDataMark = listVO.getDataIdMark();
            if (paasFormDataEntityExtList.isEmpty()) {
                continue;
            }
            List<Long> parentIdList = new ArrayList<>();
            paasFormDataEntityExtList.forEach(item -> parentIdList.add(item.getDataId()));
            boolQueryBuilder = boolQuery();
            boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
            boolQueryBuilder.filter(termsQuery(ProductEnum.getEsAttr4Keyword(ProductEnum.PARENT_ID), parentIdList));
            boolQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
            List<PaasFormDataEntityExt> childList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_PRODUCT, boolQueryBuilder, PaasFormDataEntityExt.class, null);
            Map<Long, Set<String>> spuNameMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            Map<Long, Map<String, Set<String>>> spuValueMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            for (PaasFormDataEntityExt entityExt : childList) {
                Long productId = entityExt.getData().getLong(ProductEnum.PARENT_ID.getAttr());
                if (Objects.equals(entityExt.getData().getInteger(ProductEnum.SPECIFICATION.getAttr()), 1)) {
                    //多规格
                    Set<String> nameSet = spuNameMap.getOrDefault(productId, new HashSet<>());
                    Map<String, Set<String>> valueMap = spuValueMap.getOrDefault(productId, new HashMap<>());
                    JSONObject jsonObject = JSONObject.parseObject(entityExt.getData().getString(ProductEnum.SPECIFICATION_LINK_TEXT.getAttr()));
                    for (Map.Entry<String, Object> entrySet : jsonObject.entrySet()) {
                        nameSet.add(entrySet.getKey());
                        Set<String> valueSet = valueMap.getOrDefault(entrySet.getKey(), new HashSet<>());
                        valueSet.add(entrySet.getValue().toString());
                        valueMap.put(entrySet.getKey(), valueSet);
                    }
                    spuNameMap.put(productId, nameSet);
                    spuValueMap.put(productId, valueMap);
                } else {
                    Set<String> nameSet = new HashSet<>();
                    nameSet.add(null);
                    spuNameMap.put(productId, nameSet);
                    Map<String, Set<String>> valueMap = new HashMap<>();
                    String value = entityExt.getData().getString(ProductEnum.SPECIFICATION_LINK_TEXT.getAttr());
                    value = Objects.isNull(value) ? "" : value;
                    Set<String> valueSet = new HashSet<>();
                    valueSet.add(value);
                    valueMap.put(null, valueSet);
                    spuValueMap.put(productId, valueMap);
                }
            }
            List<SpecificationEntity> specificationEntityList = new ArrayList<>();
            for (Map.Entry<Long, Set<String>> entrySet : spuNameMap.entrySet()) {
                Integer sort = 1;
                for (String name : entrySet.getValue()) {
                    SpecificationEntity entity = new SpecificationEntity();
                    entity.setCorpid(corpid);
                    entity.setProductId(entrySet.getKey());
                    entity.setName(name);
                    Map<String, Set<String>> valueMap = spuValueMap.get(entrySet.getKey());
                    if (Objects.isNull(valueMap)) {
                        continue;
                    }
                    Set<String> valueSet = valueMap.get(name);
                    if (Objects.isNull(valueSet)) {
                        continue;
                    }
                    entity.setValue(JSONObject.toJSONString(valueSet));
                    entity.setSort(sort++);
                    specificationEntityList.add(entity);
                }
            }
            LOG.warn("dataDataMark:" + dataDataMark);
            if (!specificationEntityList.isEmpty()) {
                specificationModel.insertBatch(specificationEntityList);
            }
        }
        LOG.warn("操作成功");
        return null;
    }

    @RequestMapping(value = "/fixContactCoUser", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String fixContactCoUser(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        String corpid = fixDataJobDTO.getCorpid();
        Long dataDataMark = 0L;
        List<PaasFormDataEntityExt> paasFormDataEntityExtList = new ArrayList<>();
        paasFormDataEntityExtList.add(new PaasFormDataEntityExt());
        while (!paasFormDataEntityExtList.isEmpty()) {
            BoolQueryBuilder boolQueryBuilder = boolQuery();
            boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
            boolQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
            IndexTypeEnum indexTypeEnum = indexTypeModel.getCustomerIndex(corpid, XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode(), SaasMarkEnum.SAAS.getCode());
            ListVO listVO = scriptEsHelper.list(boolQueryBuilder, 100, PaasFormDataEntityExt.class, indexTypeEnum, dataDataMark);
            paasFormDataEntityExtList = listVO.getList();
            dataDataMark = listVO.getDataIdMark();
            if (paasFormDataEntityExtList.isEmpty()) {
                continue;
            }
            List<Long> customerIdList = new ArrayList<>();
            for (PaasFormDataEntityExt entityExt : paasFormDataEntityExtList) {
                customerIdList.add(entityExt.getDataId());
            }
            boolQueryBuilder = boolQuery();
            boolQueryBuilder.filter(termsQuery(CustomerTeamEnum.getEsAttr(CustomerTeamEnum.DATA_ID), customerIdList));
            boolQueryBuilder.filter(termQuery("del", DelEnum.NORMAL.getDel()));
            boolQueryBuilder.filter(termQuery(CustomerTeamEnum.getEsAttr(CustomerTeamEnum.IS_MAIN), 0));
            IndexTypeEnum customerIndex = indexTypeModel.getCustomerTeamIndex(fixDataJobDTO.getCorpid(), XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode(), SaasMarkEnum.SAAS.getCode());
            List<PaasFormDataEntity> customerUserEntityList = esHelper.findByScroll(customerIndex, boolQueryBuilder, PaasFormDataEntity.class, null);
            List<CustomerUserEntity> userTeamEntities = (List<CustomerUserEntity>) transferSubFormHelper.transferFormDataToUserTeamList(customerIndex, customerUserEntityList);
            Map<Long, Map<String, CustomerUserEntity>> customerUserMap = new HashMap(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            for (CustomerUserEntity entity : userTeamEntities) {
                Long customerId = entity.getDataId();
                Map<String, CustomerUserEntity> userMap = customerUserMap.getOrDefault(customerId, new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY));
                userMap.put(entity.getUserId(), entity);
                customerUserMap.put(customerId, userMap);
            }
            //联系人团队
            boolQueryBuilder = boolQuery();
            boolQueryBuilder.filter(termsQuery(ContactTeamEnum.getEsAttr(ContactTeamEnum.CUSTOMER_ID), customerIdList));
            boolQueryBuilder.filter(termQuery("del", DelEnum.NORMAL.getDel()));
            List<PaasFormDataEntity> contactUserEntityList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_CONTACT_TEAM, boolQueryBuilder, PaasFormDataEntity.class, null);
            List<ContactUserEntity> userTeamEntities1 = (List<ContactUserEntity>) transferSubFormHelper.transferFormDataToUserTeamList(IndexTypeEnum.IDX_SAAS_CONTACT_TEAM, contactUserEntityList);

            Map<Long, List<String>> contactUserMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            Map<Long, Long> idMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            for (ContactUserEntity entity : userTeamEntities1) {
                Long contactId = entity.getDataId();
                Long customerId = entity.getCustomerId();
                idMap.put(contactId, customerId);
                Map<String, CustomerUserEntity> userMap = customerUserMap.getOrDefault(customerId, new HashMap<>());
                if (!contactUserMap.containsKey(contactId)) {
                    List<String> userList = new ArrayList<>(userMap.keySet());
                    contactUserMap.put(contactId, userList);
                } else {
                    contactUserMap.get(contactId).remove(entity.getUserId());
                }
            }
            List<ContactUserEntity> insertBatchList = new ArrayList<>();
            for (Map.Entry<Long, List<String>> entry : contactUserMap.entrySet()) {
                Long customerId = idMap.get(entry.getKey());
                Map<String, CustomerUserEntity> userMap = customerUserMap.get(customerId);
                for (String userId : entry.getValue()) {
                    CustomerUserEntity customerUserEntity = userMap.get(userId);
                    ContactUserEntity entity = new ContactUserEntity();
                    BeanUtil.copyProperties(customerUserEntity, entity);
                    entity.setCustomerId(customerId);
                    entity.setDataId(entry.getKey());
                    entity.setAddTime(DateTimeUtil.getInt());
                    entity.setUpdateTime(DateTimeUtil.getInt());
                    insertBatchList.add(entity);
                }
            }
            if (!insertBatchList.isEmpty()) {
                contactUserModel.insertBatch(insertBatchList, false);
            }
            LOG.warn("dataDataMark:" + dataDataMark);
        }
        LOG.warn("fixContactCoUser over");
        return null;
    }

    @RequestMapping(value = "/fixSoukeData", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String fixSearchCustomerCompanyData(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        List<String> corpidList = fixDataJobDTO.getCorpidList();
        if (CollectionsUtil.isEmpty(corpidList)) {
            // 只刷开通搜客的公司
            corpidList = searchCustomerCompanyModel.getCorpidListWithType(SoukeMealEnum.SOUKE.getType());
        }
        int index = 1;
        for (String corpid : corpidList) {
            //去掉原先isBind=2的数据（取消了权限管理中的搜客管理员），不是主账户的用户的admin=0
            SearchCustomerCompanyEntity soukeCompanyEntity = searchCustomerCompanyModel.getByCorpid(corpid, SoukeMealEnum.SOUKE.getType());
            if (soukeCompanyEntity == null) {
                continue;
            }
            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put("corpid", corpid);
            param.put("admin", 1);
            param.put("del", DelEnum.NORMAL.getDel());
            List<SearchCustomerUserEntity> entityList = searchCustomerUserModel.findEntitys(param);
            for (SearchCustomerUserEntity entity : entityList) {
                if (!Objects.equals(entity.getUserId(), soukeCompanyEntity.getUserId())) {
                    entity.setAdmin(0);
                }
                searchCustomerUserModel.update(entity);
            }
            LOG.warn("fixSoukeData------------------------" + index + "/" + corpidList.size());
            index++;
        }
        LOG.warn("操作成功");
        return null;
    }

    /**
     * 联系人团队修复
     * @param fixDataJobDTO
     * @param br
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/fixContactUsers", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String fixContactUsers(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        List<String> corpidList = fixDataJobDTO.getCorpidList();
        for (String corpid : corpidList){
            Long dataDataMark = 0L;
            List<PaasFormDataEntityExt> paasFormDataEntityExtList = new ArrayList<>();
            paasFormDataEntityExtList.add(new PaasFormDataEntityExt());
            while (!paasFormDataEntityExtList.isEmpty()) {
                BoolQueryBuilder boolQueryBuilder = boolQuery();
                if (Objects.nonNull(fixDataJobDTO.getDataId())){
                    boolQueryBuilder.filter(termQuery("dataId",fixDataJobDTO.getDataId()));
                }
                boolQueryBuilder.filter(termQuery("corpid.keyword",corpid));
                boolQueryBuilder.filter(termQuery(StringConstant.DEL,DelEnum.NORMAL.getDel()));
                ListVO listVO = scriptEsHelper.list(boolQueryBuilder, 1000, PaasFormDataEntityExt.class, IndexTypeEnum.IDX_SAAS_CONTACT, dataDataMark);
                paasFormDataEntityExtList = listVO.getList();
                dataDataMark = listVO.getDataIdMark();
                if (paasFormDataEntityExtList.isEmpty()) {
                    continue;
                }
                List<Long> contactIdList = new ArrayList<>();
                Set<Long> customerIdList = new HashSet<>();
                Map<Long,List<Long>> contactIdMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                for (PaasFormDataEntityExt entityExt : paasFormDataEntityExtList){
                    contactIdList.add(entityExt.getDataId());
                    Long customerId = entityExt.getData().getLong(ContactEnum.CUSTOMER_NAME.getAttr());
                    if (Objects.nonNull(customerId)){
                        customerIdList.add(customerId);
                    }
                    List<Long> idList = contactIdMap.getOrDefault(customerId,new ArrayList<>());
                    idList.add(entityExt.getDataId());
                    contactIdMap.put(customerId,idList);
                }
                boolQueryBuilder = boolQuery();
                boolQueryBuilder.filter(termQuery("corpid.keyword",corpid));
                boolQueryBuilder.filter(termsQuery(ContactTeamEnum.getEsAttr(ContactTeamEnum.DATA_ID), contactIdList));
                boolQueryBuilder.filter(termQuery(StringConstant.DEL,DelEnum.NORMAL.getDel()));
                List<PaasFormDataEntity> contactUserEntityList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_CONTACT_TEAM,boolQueryBuilder,PaasFormDataEntity.class,Arrays.asList(ContactTeamEnum.getAttrConnectData(ContactTeamEnum.DATA_ID), ContactTeamEnum.getAttrConnectData(ContactTeamEnum.USER_ID)));

                List<ContactUserEntity> userTeamEntities1 = (List<ContactUserEntity>) transferSubFormHelper.transferFormDataToUserTeamList(IndexTypeEnum.IDX_SAAS_CONTACT_TEAM, contactUserEntityList);

                Map<Long,List<String>> contactUserMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                for (ContactUserEntity entity : userTeamEntities1){
                    List<String> userIdList = contactUserMap.getOrDefault(entity.getDataId(),new ArrayList<>());
                    userIdList.add(entity.getUserId());
                    contactUserMap.put(entity.getDataId(),userIdList);
                }

                List<ContactUserEntity> insertList = new ArrayList<>();
                if (!customerIdList.isEmpty()){
                    boolQueryBuilder = boolQuery();
                    boolQueryBuilder.filter(termQuery("corpid.keyword",corpid));
                    boolQueryBuilder.filter(termsQuery(CustomerTeamEnum.getEsAttr(CustomerTeamEnum.DATA_ID),customerIdList));
                    boolQueryBuilder.filter(termQuery(StringConstant.DEL,DelEnum.NORMAL.getDel()));
                    IndexTypeEnum customerIndex = indexTypeModel.getCustomerTeamIndex(corpid, XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode(), SaasMarkEnum.SAAS.getCode());
                    List<PaasFormDataEntity> customerUserEntityList = esHelper.findByScroll(customerIndex,boolQueryBuilder,PaasFormDataEntity.class,Arrays.asList(CustomerTeamEnum.getAttrConnectData(CustomerTeamEnum.DATA_ID), CustomerTeamEnum.getAttrConnectData(CustomerTeamEnum.USER_ID), CustomerTeamEnum.getAttrConnectData(CustomerTeamEnum.USER_NAME), CustomerTeamEnum.getAttrConnectData(CustomerTeamEnum.IS_MAIN)));
                    List<CustomerUserEntity> userTeamEntities = (List<CustomerUserEntity>) transferSubFormHelper.transferFormDataToUserTeamList(customerIndex, customerUserEntityList);
                    for (CustomerUserEntity entity : userTeamEntities){
                        if (contactIdMap.containsKey(entity.getDataId())){
                            List<Long> idList = contactIdMap.get(entity.getDataId());
                            for (Long contactId : idList){
                                if (contactUserMap.containsKey(contactId)){
                                    List<String> userIdList = contactUserMap.get(contactId);
                                    if (!userIdList.contains(entity.getUserId())){
                                        ContactUserEntity contactUserEntity = new ContactUserEntity();
                                        contactUserEntity.setCorpid(corpid);
                                        contactUserEntity.setUserId(entity.getUserId());
                                        contactUserEntity.setUserName(entity.getUserName());
                                        contactUserEntity.setCustomerId(entity.getDataId());
                                        contactUserEntity.setDataId(contactId);
                                        contactUserEntity.setIsMain(entity.getIsMain());
                                        insertList.add(contactUserEntity);
                                    }
                                }
                            }
                        }
                    }
                }
                if (!insertList.isEmpty()){
                    contactUserModel.insertBatch(insertList, false);
                }
                LOG.warn(corpid + "----------------" + dataDataMark);
            }
        }
        LOG.warn("fixContactUsers over");
        return null;
    }

    /**
     * Description: 工单协同人（解释放出来）
     * @param fixDataJobDTO
     * @return br
     * @throws
     * @author 刘阳
     * @date 2019/12/3 4:20 PM
     * @since v1.0
     */
    @RequestMapping(value = "/changeWorkOrderCouserIdShowType", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String changeWorkOrderCouserId(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        List<String> corpidList = paasFormExplainModel.getCorpidList();
        Integer index = 1;
        Integer total = corpidList.size();
        for (String corpid : corpidList){
            Map<String,Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put("corpid",corpid);
            param.put("del",0);
            List<WorkOrderExplainEntity> paasFormExplainEntityExtList = workOrderExplainModel.findEntitys(param);
            for (WorkOrderExplainEntity entityExt : paasFormExplainEntityExtList){
                List<FieldAttrEntity> fieldAttrEntityList = JSONArray.parseArray(entityExt.getExplains(), FieldAttrEntity.class);
                for (FieldAttrEntity fieldAttrEntity : fieldAttrEntityList){
                    if (Objects.equals(fieldAttrEntity.getAttr(), WorkOrderEnum.COUSERID.getAttr())) {
                        fieldAttrEntity.setShowType(ShowTypeEnum.ALL.getCode());
                        fieldAttrEntity.setIsForbidden(0);
                        fieldAttrEntity.setRequired(0);
                        //可新增权限：默认【超级管理员、工单主管、创建人、负责人、负责人主管】可新增协同人，支持自定义；
                        fieldAttrEntity.setShowEditable(0);
                        fieldAttrEntity.setAdd(1);
                        fieldAttrEntity.setAddAdvanceEnable(1);
                        fieldAttrEntity.setShowAdd(1);
                        fieldAttrEntity.setRemove(1);
                        fieldAttrEntity.setRemoveAdvanceEnable(1);
                        fieldAttrEntity.setShowRemove(1);
                        fieldAttrEntity.setSetType(3);
                        fieldAttrEntity.setEditable(1);
                        fieldAttrEntity.setUnableEditMemo(null);
                        fieldAttrEntity.setAddRule(FormDataFormExplainHelper.getDefaultRule(RoleEnum.WORKORDER_MANAGER));
                        fieldAttrEntity.setRemoveRule(FormDataFormExplainHelper.getDefaultRule(RoleEnum.WORKORDER_MANAGER));
                        VisibleRulePoJo editableRule = new VisibleRulePoJo();
                        fieldAttrEntity.setEditableRule(editableRule);
                    }
                }
                entityExt.setExplains(JSONArray.toJSONString(fieldAttrEntityList));
                workOrderExplainModel.update(entityExt);
            }
            LOG.warn("fix explain:" + index + "/" + total);
            index ++;
        }
        return null;
    }


    @RequestMapping(value = "/removeCustomerExcessUser", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String removeCustomerExcessUser(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        List<String> corpidList = fixDataJobDTO.getCorpidList();
        for (String corpid : corpidList) {
            Map<String, Object> param = new HashMap<>(16);
            param.put(ParameterConstant.CORPID, corpid);
            param.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
            Integer totalCount = customerModel.getEntitysCount(param);
            LOG.warn("该公司数据库中共有客户" + totalCount + "条数据");

            Integer pageSize = 1000;
            int totalPage = (totalCount % pageSize == 0) ? (totalCount / pageSize) : (totalCount / pageSize) + 1;
            Integer page = 1;
            Long dataDataMark = 0L;
            List<PaasFormDataEntityExt> paasFormDataEntityExtList = new ArrayList<>();
            paasFormDataEntityExtList.add(new PaasFormDataEntityExt());
            while (!paasFormDataEntityExtList.isEmpty()) {
                BoolQueryBuilder boolQueryBuilder = boolQuery();
                boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
                boolQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
                IndexTypeEnum indexTypeEnum = indexTypeModel.getCustomerIndex(corpid, XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode(), SaasMarkEnum.SAAS.getCode());
                ListVO listVO = scriptEsHelper.list(boolQueryBuilder, 1000, PaasFormDataEntityExt.class, indexTypeEnum, dataDataMark, Collections.singletonList(FieldTypeEnum.DATAID.getAlias()));
                paasFormDataEntityExtList = listVO.getList();
                dataDataMark = listVO.getDataIdMark();
                if (paasFormDataEntityExtList.isEmpty()) {
                    continue;
                }
                List<Long> customerIdList = new ArrayList<>();
                for (PaasFormDataEntityExt entityExt : paasFormDataEntityExtList) {
                    customerIdList.add(entityExt.getDataId());
                }
                boolQueryBuilder = boolQuery();
                boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
                boolQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
                boolQueryBuilder.filter(termsQuery(CustomerTeamEnum.getEsAttr(CustomerTeamEnum.DATA_ID), customerIdList));
                IndexTypeEnum customerIndex = indexTypeModel.getCustomerTeamIndex(corpid, XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode(), SaasMarkEnum.SAAS.getCode());
                List<PaasFormDataEntity> customerUserEntities = esHelper.findByScroll(customerIndex, boolQueryBuilder, PaasFormDataEntity.class, Arrays.asList("id", CustomerTeamEnum.getAttrConnectData(CustomerTeamEnum.DATA_ID), CustomerTeamEnum.getAttrConnectData(CustomerTeamEnum.USER_ID)));
                List<CustomerUserEntity> userTeamEntities = (List<CustomerUserEntity>) transferSubFormHelper.transferFormDataToUserTeamList(customerIndex, customerUserEntities);

                List<Long> removeIds = new ArrayList<>();
                Map<Long, List<String>> userMap = new HashMap<>();
                for (CustomerUserEntity entity : userTeamEntities) {
                    String userId = entity.getUserId();
                    Long dataId = entity.getDataId();
                    List<String> integerList = userMap.get(dataId);
                    if (Objects.isNull(integerList)) {
                        integerList = new ArrayList<>();
                        integerList.add(userId);
                        userMap.put(dataId, integerList);
                    } else if (integerList.contains(userId)){
                        // 这个客户的团队有重复的人员
                        removeIds.add(entity.getId());
                    } else {
                        integerList.add(userId);
                        userMap.put(dataId, integerList);
                    }
                }
                if (!removeIds.isEmpty()) {
                    customerUserModel.batchDeleteById(corpid, removeIds, WriteRequest.RefreshPolicy.WAIT_UNTIL);
                }
                LOG.warn("---------------------------" + page + "/" + totalPage);
                page++;
            }
        }
        LOG.warn("removeCustomerExcessUser over");
        return null;
    }
    @RequestMapping(value = "/repairInvoiceRelationshipData", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String repairSerialData(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws XbbException {
        XbbResponse<ScriptVO> response;
        if ( br.hasErrors() ) {
            String errMsg = Objects.requireNonNull(br.getFieldError()).getDefaultMessage();
            response = new XbbResponse<>(SystemErrorCodeEnum.API_ERROR_100002, errMsg);
        } else {
            try {
                if ( !proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode()) ) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
                }
                ScriptVO detailTabScriptVO = repairExplainService.scriptInvoiceRelationship(fixDataJobDTO);
                response = new XbbResponse<>(detailTabScriptVO);
            } catch (XbbException e) {
                response = new XbbResponse<>(e);
            }
        }
        return JSON.toJSONString(response);
    }

    @RequestMapping(value = "/repairApproveData", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String repairApproveData(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws XbbException {
        XbbResponse<ScriptVO> response;
        if ( br.hasErrors() ) {
            String errMsg = Objects.requireNonNull(br.getFieldError()).getDefaultMessage();
            response = new XbbResponse<>(SystemErrorCodeEnum.API_ERROR_100002, errMsg);
        } else {
            try {
                if ( !proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode()) ) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
                }
                ScriptVO detailTabScriptVO = repairExplainService.scriptApproveData(fixDataJobDTO);
                response = new XbbResponse<>(detailTabScriptVO);
            } catch (XbbException e) {
                response = new XbbResponse<>(e);
            }
        }
        return JSON.toJSONString(response);
    }

    @RequestMapping(value = "/repairInvoiceAmountData", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String repairInvoiceAmountData(@RequestBody @Valid RepairInvoiceAmountDTO repairInvoiceAmountDTO, BindingResult br) throws XbbException {
        XbbResponse<ScriptVO> response;
        if ( br.hasErrors() ) {
            String errMsg = Objects.requireNonNull(br.getFieldError()).getDefaultMessage();
            response = new XbbResponse<>(SystemErrorCodeEnum.API_ERROR_100002, errMsg);
        } else {
            try {
                if ( !proBaseConfig.getXbbCode().equals(repairInvoiceAmountDTO.getXbbCode()) ) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
                }
                ScriptVO detailTabScriptVO = repairExplainService.scriptInvoiceAmountData(repairInvoiceAmountDTO);
                response = new XbbResponse<>(detailTabScriptVO);
            } catch (XbbException e) {
                response = new XbbResponse<>(e);
            }
        }
        return JSON.toJSONString(response);
    }

    @RequestMapping(value = "/repairInvoiceRelationshipMoney", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String repairInvoiceRelationshipMoney(@RequestBody @Valid RepairInvoiceAmountDTO repairInvoiceAmountDTO, BindingResult br) throws XbbException {
        XbbResponse<ScriptVO> response;
        if ( br.hasErrors() ) {
            String errMsg = Objects.requireNonNull(br.getFieldError()).getDefaultMessage();
            response = new XbbResponse<>(SystemErrorCodeEnum.API_ERROR_100002, errMsg);
        } else {
            try {
                String xbbCode = repairInvoiceAmountDTO.getXbbCode();
                if ( !Objects.equals(proBaseConfig.getXbbCode(), xbbCode)) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
                }
                ScriptVO detailTabScriptVO = repairExplainService.repairInvoiceRelationshipMoney(repairInvoiceAmountDTO);
                response = new XbbResponse<>(detailTabScriptVO);
            } catch (XbbException e) {
                response = new XbbResponse<>(e);
            }
        }
        return JSON.toJSONString(response);
    }

    @RequestMapping(value = "/repairPurchaseInvoiceRelationshipMoney", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String repairPurchaseInvoiceRelationshipMoney(@RequestBody @Valid RepairInvoiceAmountDTO repairInvoiceAmountDTO, BindingResult br) throws XbbException {
        XbbResponse<ScriptVO> response;
        if ( br.hasErrors() ) {
            String errMsg = Objects.requireNonNull(br.getFieldError()).getDefaultMessage();
            response = new XbbResponse<>(SystemErrorCodeEnum.API_ERROR_100002, errMsg);
        } else {
            try {
                String xbbCode = repairInvoiceAmountDTO.getXbbCode();
                if ( !Objects.equals(proBaseConfig.getXbbCode(), xbbCode)) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
                }
                ScriptVO detailTabScriptVO = repairExplainService.repairPurchaseInvoiceRelationshipMoney(repairInvoiceAmountDTO);
                response = new XbbResponse<>(detailTabScriptVO);
            } catch (XbbException e) {
                response = new XbbResponse<>(e);
            }
        }
        return JSON.toJSONString(response);
    }

    @RequestMapping(value = "/repairInvoiceRelationshipSpecialMoney", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String repairInvoiceRelationshipSpecialMoney(@RequestBody @Valid RepairInvoiceRelationMoneyDTO repairInvoiceRelationMoneyDTO, BindingResult br) throws XbbException {
        XbbResponse<ScriptVO> response;
        if ( br.hasErrors() ) {
            String errMsg = Objects.requireNonNull(br.getFieldError()).getDefaultMessage();
            response = new XbbResponse<>(SystemErrorCodeEnum.API_ERROR_100002, errMsg);
        } else {
            try {
                if ( !proBaseConfig.getXbbCode().equals(repairInvoiceRelationMoneyDTO.getXbbCode())) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
                }
                ScriptVO detailTabScriptVO = repairExplainService.repairInvoiceRelationshipSpecialMoney(repairInvoiceRelationMoneyDTO);
                response = new XbbResponse<>(detailTabScriptVO);
            } catch (XbbException e) {
                response = new XbbResponse<>(e);
            }
        }
        return JSON.toJSONString(response);
    }

    @RequestMapping(value = "/repairBatchInvoiceRelationshipMoney", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String repairBatchInvoiceRelationshipMoney(@RequestBody @Valid RepairInvoiceRelationMoneyDTO repairInvoiceRelationMoneyDTO, BindingResult br) throws XbbException {
        XbbResponse<ScriptVO> response;
        if ( br.hasErrors() ) {
            String errMsg = Objects.requireNonNull(br.getFieldError()).getDefaultMessage();
            response = new XbbResponse<>(SystemErrorCodeEnum.API_ERROR_100002, errMsg);
        } else {
            try {
                if ( !proBaseConfig.getXbbCode().equals(repairInvoiceRelationMoneyDTO.getXbbCode())) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
                }
                ScriptVO detailTabScriptVO = repairExplainService.repairBatchInvoiceRelationshipMoney(repairInvoiceRelationMoneyDTO);
                response = new XbbResponse<>(detailTabScriptVO);
            } catch (XbbException e) {
                response = new XbbResponse<>(e);
            }
        }
        return JSON.toJSONString(response);
    }

    @RequestMapping(value = "/repairContractAmountData", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String repairContractAmountData(@RequestBody @Valid RepairContractBadAmountDTO repairContractBadAmountDTO, BindingResult br) throws XbbException {
        XbbResponse<ScriptVO> response;
        if ( br.hasErrors() ) {
            String errMsg = Objects.requireNonNull(br.getFieldError()).getDefaultMessage();
            response = new XbbResponse<>(SystemErrorCodeEnum.API_ERROR_100002, errMsg);
        } else {
            try {
                if ( !proBaseConfig.getXbbCode().equals(repairContractBadAmountDTO.getXbbCode()) ) {
                    throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
                }
                ScriptVO detailTabScriptVO = repairExplainService.scriptContractInvoiceAmountData(repairContractBadAmountDTO);
                response = new XbbResponse<>(detailTabScriptVO);
            } catch (XbbException e) {
                response = new XbbResponse<>(e);
            }
        }
        return JSON.toJSONString(response);
    }



    /**
     * 修复线上工作报告脏数据
     * @param fixDataJobDTO
     * @param br
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/updateWorkOrderForm", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String updateWorkOrderForm(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006);
        }
        List<String> corpidList = fixDataJobDTO.getCorpidList();
        if (CollectionsUtil.isEmpty(corpidList)) {
            corpidList = companyModel.getCorpidList();
        }
        LOG.info("数据库中共有公司" + corpidList.size() + "家");
        for (String corpid : corpidList) {
            // 查询日报，周报，月报对应的模版
            Map<String,Object> paasFormParam = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            paasFormParam.put(StringConstant.CORPID,corpid);
            paasFormParam.put("businessTypeList",Arrays.asList(XbbRefTypeEnum.WORKREPORT_DAILY.getCode(), XbbRefTypeEnum.WORKREPORT_WEEKLY.getCode(), XbbRefTypeEnum.WORKREPORT_MONTHLY.getCode()));
            paasFormParam.put("del",DelEnum.NORMAL.getDel());
            List<PaasFormEntityExt> paasFormEntityList = paasFormModel.findEntitys(paasFormParam);
            HashMap<Integer, Long> paasFormMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            paasFormEntityList.forEach(item -> paasFormMap.put(item.getBusinessType(), item.getId()));

            if(paasFormMap.isEmpty()){
                continue;
            }

            // 查询公司中错误的数据
            // 日报模版
            Long dailyFormId = paasFormMap.get(XbbRefTypeEnum.WORKREPORT_DAILY.getCode());
            if(dailyFormId != null){
                BoolQueryBuilder dailyBoolQueryBuilder = boolQuery();
                dailyBoolQueryBuilder.filter(termQuery(ParameterConstant.CORPID + StringConstant.POINT + StringConstant.KEY_WORD, corpid));
                dailyBoolQueryBuilder.filter(termQuery(ParameterConstant.DEL, DelEnum.NORMAL.getDel()));
                dailyBoolQueryBuilder.filter(termQuery("data." + WorkReportDailyEnum.TYPE.getAttr() + ".keyword", 1));
                dailyBoolQueryBuilder.mustNot(termQuery("formId", dailyFormId));
                List<String> dailyFieldList = new ArrayList<>();
                dailyFieldList.add(FieldTypeEnum.DATAID.getAlias());
                dailyFieldList.add(StringConstant.CORPID);
                dailyFieldList.add("formId");
                List<WorkReportEntityExt> workReportDailyList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_WORK_REPORT, dailyBoolQueryBuilder, WorkReportEntityExt.class, dailyFieldList);
                int dailyTotalCount = workReportDailyList.size();
                LOG.info("该公司"+ corpid +"在es中共有" + dailyTotalCount + "条日报错误数据需要修复");

                if(dailyTotalCount != 0){
                    List<UpdateDataEntity> dailyList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    LOG.info("开始更新公司"+ corpid + "日报");
                    workReportDailyList.forEach(item -> {
                        UpdateDataEntity updateDataEntity = new UpdateDataEntity();
                        updateDataEntity.setId(item.getDataId());
                        updateDataEntity.setCorpid(item.getCorpid());
                        updateDataEntity.setFormId(dailyFormId);
                        updateDataEntity.setData(new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY));
                        dailyList.add(updateDataEntity);
                    });
                    // workReportModel.updateBatchForm(dailyList, corpid);
                    LOG.info("更新公司"+ corpid + "日报结束");
                }
            }

            // 周报模版
            Long weekFormId = paasFormMap.get(XbbRefTypeEnum.WORKREPORT_WEEKLY.getCode());
            if(weekFormId != null){
                BoolQueryBuilder weekBoolQueryBuilder = boolQuery();
                weekBoolQueryBuilder.filter(termQuery(ParameterConstant.CORPID + StringConstant.POINT + StringConstant.KEY_WORD, corpid));
                weekBoolQueryBuilder.filter(termQuery(ParameterConstant.DEL, DelEnum.NORMAL.getDel()));
                weekBoolQueryBuilder.filter(termQuery("data." + WorkReportWeeklyEnum.TYPE.getAttr() + ".keyword", 2));
                weekBoolQueryBuilder.mustNot(termQuery("formId", weekFormId));
                List<String> weekFieldList = new ArrayList<>();
                weekFieldList.add(FieldTypeEnum.DATAID.getAlias());
                weekFieldList.add(StringConstant.CORPID);
                weekFieldList.add("formId");
                List<WorkReportEntityExt> workReportWeekList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_WORK_REPORT, weekBoolQueryBuilder, WorkReportEntityExt.class, weekFieldList);
                int weekTotalCount = workReportWeekList.size();
                LOG.info("该公司"+ corpid +"在es中共有" + weekTotalCount + "条周报错误数据需要修复");

                if(weekTotalCount != 0){
                    List<UpdateDataEntity> weekList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    LOG.info("开始更新公司"+ corpid + "周报");
                    workReportWeekList.forEach(item -> {
                        UpdateDataEntity updateDataEntity = new UpdateDataEntity();
                        updateDataEntity.setId(item.getDataId());
                        updateDataEntity.setCorpid(item.getCorpid());
                        updateDataEntity.setFormId(weekFormId);
                        updateDataEntity.setData(new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY));
                        weekList.add(updateDataEntity);
                    });
                    // workReportModel.updateBatchForm(weekList, corpid);
                    LOG.info("更新公司"+ corpid + "周报结束");
                }
            }

            // 月报模版
            Long monthFormId = paasFormMap.get(XbbRefTypeEnum.WORKREPORT_MONTHLY.getCode());
            if(monthFormId != null){
                BoolQueryBuilder monthBoolQueryBuilder = boolQuery();
                monthBoolQueryBuilder.filter(termQuery(ParameterConstant.CORPID + StringConstant.POINT + StringConstant.KEY_WORD, corpid));
                monthBoolQueryBuilder.filter(termQuery(ParameterConstant.DEL, DelEnum.NORMAL.getDel()));
                monthBoolQueryBuilder.filter(termQuery("data." + WorkReportMonthlyEnum.TYPE.getAttr() + ".keyword", 3));
                monthBoolQueryBuilder.mustNot(termQuery("formId", monthFormId));
                List<String> monthFieldList = new ArrayList<>();
                monthFieldList.add(FieldTypeEnum.DATAID.getAlias());
                monthFieldList.add(StringConstant.CORPID);
                monthFieldList.add("formId");
                List<WorkReportEntityExt> workReportMonthList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_WORK_REPORT, monthBoolQueryBuilder, WorkReportEntityExt.class, monthFieldList);
                int monthTotalCount = workReportMonthList.size();
                LOG.info("该公司"+ corpid +"在es中共有" + monthTotalCount + "条月报错误数据需要修复");

                if(monthTotalCount != 0){
                    List<UpdateDataEntity> monthList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    LOG.info("开始更新公司"+ corpid + "月报");
                    workReportMonthList.forEach(item -> {
                        UpdateDataEntity updateDataEntity = new UpdateDataEntity();
                        updateDataEntity.setId(item.getDataId());
                        updateDataEntity.setCorpid(item.getCorpid());
                        updateDataEntity.setFormId(monthFormId);
                        updateDataEntity.setData(new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY));
                        monthList.add(updateDataEntity);
                    });
                    workReportModel.updateBatch(monthList, corpid);
                    LOG.info("更新公司"+ corpid + "月报结束");
                }
            }
        }
        LOG.info("操作成功");
        return null;
    }


    @RequestMapping(value = "/fixBomBillExplain", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String fixBomBillExplain(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        long start = DateTimeUtil.getInt();
        List<String> corpidList = companyModel.getCorpidList();
        int index = 1;
        for (String corpid : corpidList) {
            LOG.warn("fixBomBillandProductionOrder:" + index + "/" + corpidList.size());
            index++;
            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put("corpid", corpid);
            param.put("del", 0);
            param.put("businessType",XbbRefTypeEnum.BOM_BILL.getCode());
            List<PaasFormExplainEntity> paasFormExplainEntityList = paasFormExplainModel.list(param);
            for (PaasFormExplainEntity entity : paasFormExplainEntityList) {
                boolean update = false;
                List<FieldAttrEntity> fieldAttrEntityList = JSONArray.parseArray(entity.getExplains(), FieldAttrEntity.class);
                for (FieldAttrEntity fieldAttrEntity : fieldAttrEntityList) {
                    if (Objects.equals(fieldAttrEntity.getAttr(),BomBillEnum.PRODUCT.getAttr()) || Objects.equals(fieldAttrEntity.getAttr(),BomBillEnum.MATERIEL.getAttr())) {
                        fieldAttrEntity.setShowType(ShowTypeEnum.ALL.getCode());
                        update=true;
                    }else if (Objects.equals(fieldAttrEntity.getAttr(),BomBillEnum.PRODUCT_NAME.getAttr())
                            || Objects.equals(fieldAttrEntity.getAttr(),BomBillEnum.PRODUCT_NO.getAttr())
                            || Objects.equals(fieldAttrEntity.getAttr(),BomBillEnum.PRODUCT_SPECIFICATION.getAttr())
                            || Objects.equals(fieldAttrEntity.getAttr(),BomBillEnum.PRODUCT_UNIT.getAttr())) {
                        fieldAttrEntity.setShowType(ShowTypeEnum.NONE.getCode());
                        update=true;
                    }
                }
                if (update) {
                    entity.setExplains(JSONArray.toJSONString(fieldAttrEntityList));
                    paasFormExplainModel.update(entity);
                }
            }
        }
        LOG.warn("consume:" + (DateTimeUtil.getInt() - start));
        LOG.warn("fixBomBillandProductionOrder over");
        return null;
    }

    @RequestMapping(value = "/fixProductionOrderExplain", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String fixProductionOrderExplain(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        long start = DateTimeUtil.getInt();
        List<String> corpidList = companyModel.getCorpidList();
        int index = 1;
        for (String corpid : corpidList) {
            LOG.warn("fixProductionOrderExplain:" + index + "/" + corpidList.size());
            index++;
            Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            param.put("corpid", corpid);
            param.put("del", 0);
            param.put("businessType",XbbRefTypeEnum.PRODUCTION_ORDER.getCode());
            List<PaasFormExplainEntity> paasFormExplainEntityList = paasFormExplainModel.list(param);
            for (PaasFormExplainEntity entity : paasFormExplainEntityList) {
                boolean update = false;
                List<FieldAttrEntity> fieldAttrEntityList = JSONArray.parseArray(entity.getExplains(), FieldAttrEntity.class);
                for (FieldAttrEntity fieldAttrEntity : fieldAttrEntityList) {
                    if (Objects.equals(fieldAttrEntity.getAttr(),ProductionOrderEnum.PRODUCT.getAttr()) || Objects.equals(fieldAttrEntity.getAttr(),ProductionOrderEnum.MATERIEL.getAttr())) {
                        fieldAttrEntity.setShowType(ShowTypeEnum.ALL.getCode());
                        update=true;
                    }else if (Objects.equals(fieldAttrEntity.getAttr(),ProductionOrderEnum.PRODUCT_NAME.getAttr()) || Objects.equals(fieldAttrEntity.getAttr(),ProductionOrderEnum.PRODUCT_NO.getAttr())) {
                        fieldAttrEntity.setShowType(ShowTypeEnum.NONE.getCode());
                        update=true;
                    } else if (Objects.equals(fieldAttrEntity.getAttr(),ProductionOrderEnum.BOM_VERSION.getAttr())){
                        fieldAttrEntity.setForbiddenSettingList(Collections.singletonList(ForbiddenSettingEnum.DISABLE_TYPE.getAlias()));
                        update = true;
                    }
                }
                if (update) {
                    entity.setExplains(JSONArray.toJSONString(fieldAttrEntityList));
                    paasFormExplainModel.update(entity);
                }
            }
        }
        LOG.warn("consume:" + (DateTimeUtil.getInt() - start));
        LOG.warn("fixProductionOrderExplain over");
        return null;
    }


    @RequestMapping(value = "/returnPurchaseFixSupplier", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String returnPurchaseFixSupplier(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        long start = DateTimeUtil.getInt();
//        List<String> corpidList = companyModel.getCorpidList();
//        LOG.warn("returnPurchaseFixSupplier:" + corpidList.size());
//        Integer index = 0;
//        for (String corpid : corpidList){
//            index ++;
//            LOG.warn("corpid:" + corpid + "," +index + "/" + corpidList.size());
            BoolQueryBuilder boolQueryBuilder = boolQuery();
//            boolQueryBuilder.filter(termQuery("corpid.keyword",corpid));
            boolQueryBuilder.filter(termQuery(StringConstant.DEL,DelEnum.NORMAL.getDel()));
            List<PaasFormDataEntity> paasFormDataEntityList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_RETURNED_PURCHASE,boolQueryBuilder,PaasFormDataEntity.class,null);
            List<Long> supplierIdList = new ArrayList<>();
            for (PaasFormDataEntity entity : paasFormDataEntityList){
                if (Objects.nonNull(entity.getData().getLong(ReturnedPurchaseEnum.SUPPLIER_ID.getAttr()))){
                    supplierIdList.add(entity.getData().getLong(ReturnedPurchaseEnum.SUPPLIER_ID.getAttr()));
                }
            }

            boolQueryBuilder = boolQuery();
//            boolQueryBuilder.filter(termQuery("corpid.keyword",corpid));
            boolQueryBuilder.filter(termsQuery(FieldTypeEnum.DATAID.getAlias(),supplierIdList));
            List<PaasFormDataEntity> supplierList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_SUPPLIER,boolQueryBuilder,PaasFormDataEntity.class,null);
            Map<Long,String> supplierNameMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            for (PaasFormDataEntity entity : supplierList){
                supplierNameMap.put(entity.getDataId(),entity.getData().getString(SupplierEnum.SUPPLIER_NAME.getAttr()));
            }
            Map<String,List<UpdateDataEntity>> updateMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            for (PaasFormDataEntity entity : paasFormDataEntityList){
                JSONObject jsonObject = new JSONObject();
                Long supplierId = entity.getData().getLong(ReturnedPurchaseEnum.SUPPLIER_ID.getAttr());
                if (Objects.isNull(supplierId)){
                    continue;
                }
                jsonObject.put(ReturnedPurchaseEnum.LINK_SUPPLIER.getAttr(),supplierId);
                jsonObject.put(ReturnedPurchaseEnum.LINK_SUPPLIER_HIDE.getAttr(),supplierNameMap.getOrDefault(supplierId,""));
                String corpid = entity.getCorpid();
                List<UpdateDataEntity> updateDataEntityList = updateMap.getOrDefault(corpid,new ArrayList<>());
                updateDataEntityList.add(ExplainUtil.getUpdateData(entity.getDataId(),jsonObject,corpid));
                updateMap.put(corpid,updateDataEntityList);
            }
            for (Map.Entry<String, List<UpdateDataEntity>> entry : updateMap.entrySet()) {
                returnedPurchaseModel.updateBatch(entry.getValue(),entry.getKey());
            }
//        }
        LOG.warn("consume:" + (DateTimeUtil.getInt() - start));
        LOG.warn("returnPurchaseFixSupplier over");
        return null;
    }

    @RequestMapping(value = "/fixNullArray", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String fixNullArray(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        long start = DateTimeUtil.getInt();
        List<String> corpidList = companyModel.getCorpidList();
        LOG.warn("fixNullArray:" + corpidList.size());
        Integer index = 0;
        for (String corpid : corpidList){
            index ++;
            LOG.warn("fixNullArray:" + index + "/" + corpidList.size());
            List<WorkOrderEntity> workOrderEntityList = workOrderModel.findNullArrayData(corpid);
            List<Long> workOrderIdList = new ArrayList<>();
            workOrderEntityList.forEach(item -> workOrderIdList.add(item.getId()));
            if (workOrderIdList.isEmpty()){
                continue;
            }
            Map<String,Object> map = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            map.put("corpid",corpid);
            map.put("del",0);
            map.put("workOrderIdIn",workOrderIdList);
            List<WorkOrderProductEntity> workOrderProductEntityList = workOrderProductModel.findEntitys(map);
            Map<Long,Set<Long>> setMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            for (WorkOrderProductEntity entity : workOrderProductEntityList){
                Set<Long> productIdSet = setMap.getOrDefault(entity.getWorkOrderId(),new HashSet<>());
                productIdSet.add(entity.getProductId());
                setMap.put(entity.getWorkOrderId(),productIdSet);
            }
            List<UpdateDataEntity> updateList = new ArrayList<>();
            for (WorkOrderEntity entity : workOrderEntityList){
                Set<Long> productIdSet = setMap.getOrDefault(entity.getId(),new HashSet<>());
                JSONObject data = new JSONObject();
                data.put(WorkOrderEnum.SPARE_PARTS.getAttr(),productIdSet);
                updateList.add(ExplainUtil.getUpdateData(entity.getId(),data,corpid));
            }
            if (!updateList.isEmpty()){
                workOrderModel.updateBatch(updateList,corpid);
            }
        }
        LOG.warn("consume:" + (DateTimeUtil.getInt() - start));
        LOG.warn("fixNullArray over");
        return null;
    }

    @RequestMapping(value = "/fixLostCostProduct", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String fixLostCostProduct(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        long start = DateTimeUtil.getInt();
        List<String> corpidList = productModel.getCorpidList();
        LOG.warn("fixLostCostProduct:" + corpidList.size());
        Integer index = 0;
        for (String corpid : corpidList) {
            index++;
            LOG.warn(corpid + ":" + + index + "/" + corpidList.size());
            BoolQueryBuilder boolQueryBuilder = boolQuery();
            boolQueryBuilder.filter(termQuery("corpid.keyword",corpid));
            boolQueryBuilder.mustNot(existsQuery(ProductEnum.getAttrConnectData(ProductEnum.COST)));
            boolQueryBuilder.filter(termQuery("del",DelEnum.NORMAL.getDel()));
            List<PaasFormDataEntityExt> paasFormDataEntityExtList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_PRODUCT,boolQueryBuilder,PaasFormDataEntityExt.class,Arrays.asList(FieldTypeEnum.DATAID.getAlias(),ProductEnum.getAttrConnectData(ProductEnum.PARENT_ID)));
            //最多的一家公司1100左右脏数据，顶得住
            List<UpdateDataEntity> updateList = new ArrayList<>();
//            List<Long> childProductIdList = new ArrayList<>();
            for (PaasFormDataEntityExt paasFormDataEntityExt : paasFormDataEntityExtList){
//                if (Objects.equals(paasFormDataEntityExt.getData().getLong(ProductEnum.PARENT_ID.getAttr()),0L)){
                    JSONObject data = new JSONObject();
                    data.put(ProductEnum.COST.getAttr(),0D);
                    updateList.add(ExplainUtil.getUpdateData(paasFormDataEntityExt.getDataId(),data,corpid));
//                }else {
//                    childProductIdList.add(paasFormDataEntityExt.getDataId());
//                }
            }
            List<ProductWarehouseEntity> productWarehouseUpdateList = new ArrayList<>();
           /* if (!childProductIdList.isEmpty()){
                boolQueryBuilder = boolQuery();
                boolQueryBuilder.filter(termQuery("corpid.keyword",corpid));
                boolQueryBuilder.filter(termsQuery("productId",childProductIdList));
                boolQueryBuilder.filter(termQuery("warehouseChecked",1));
                boolQueryBuilder.filter(termQuery("del",0));
                List<ProductWarehouseEntity> productWarehouseEntityList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_PRODUCT_WAREHOUSE,boolQueryBuilder,ProductWarehouseEntity.class,null);
                Map<Long,Double> stockMap = new HashMap<>();
                Map<Long,Double> costMap = new HashMap<>();
                for (ProductWarehouseEntity entity : productWarehouseEntityList){
                    if (Objects.isNull(entity.getCost())){
                        entity.setCost(0D);
                        productWarehouseUpdateList.add(entity);
                    }else if (entity.getNum() > 0){
                        Double stock = stockMap.getOrDefault(entity.getProductId(), 0D);
                        stock = Arith.add(stock,entity.getNum());
                        stockMap.put(entity.getProductId(),stock);
                        Double cost = costMap.getOrDefault(entity.getProductId(),0D);
                        cost = Arith.add(cost,Arith.sub(entity.getCost(),stock));
                        costMap.put(entity.getProductId(),cost);
                    }
                }
                for (Long productId : childProductIdList){
                    JSONObject data = new JSONObject();
                    if (stockMap.containsKey(productId)){
                        Double stock = stockMap.get(productId);
                        Double cost = costMap.getOrDefault(productId,0D);
                        cost = Arith.div(cost,stock);
                        data.put(ProductEnum.STOCK.getAttr(),stock);
                        data.put(ProductEnum.COST.getAttr(),cost);
                    }else{
                        data.put(ProductEnum.STOCK.getAttr(),0D);
                        data.put(ProductEnum.COST.getAttr(),0D);
                    }
                    updateList.add(ExplainUtil.getUpdateData(productId,data,corpid));
                }
            }*/
            if (!updateList.isEmpty()){
                productModel.updateBatch(updateList,corpid);
            }
//            if (!productWarehouseUpdateList.isEmpty()){
//                productWarehouseModel.updateStockBatch(productWarehouseUpdateList,corpid);
//            }
        }
        LOG.warn("consume:" + (DateTimeUtil.getInt() - start));
        LOG.warn("fixLostCostProduct over2");
        return null;
    }

    @RequestMapping(value = "/fixParentProductDataWarehouse", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String fixParentProductDataWarehouse(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        List<String> corpidList = fixDataJobDTO.getCorpidList();
        if (CollectionsUtil.isEmpty(corpidList)) {
            corpidList = productModel.getCorpidList();
        }
        long start = DateTimeUtil.getInt();
        int index = 1;
        for (String corpid : corpidList){
            LOG.warn("fixParentProductDataWarehouse " + corpid + ":" + index + "/" + corpidList.size());
            index++;
            Long dataDataMark = 0L;
            List<PaasFormDataEntityExt> paasFormDataEntityExtList = new ArrayList<>();
            paasFormDataEntityExtList.add(new PaasFormDataEntityExt());
            while (!paasFormDataEntityExtList.isEmpty()) {
                //父产品数据
                BoolQueryBuilder boolQueryBuilder = boolQuery();
                boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
                boolQueryBuilder.filter(termQuery(ProductEnum.getAttrConnectData(ProductEnum.PARENT_ID), 0));
                boolQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
                ListVO listVO = scriptEsHelper.list(boolQueryBuilder, 1000, PaasFormDataEntityExt.class, IndexTypeEnum.IDX_SAAS_PRODUCT, dataDataMark);
                paasFormDataEntityExtList = listVO.getList();
                dataDataMark = listVO.getDataIdMark();
                if (paasFormDataEntityExtList.isEmpty()) {
                    continue;
                }
                List<Long> spuIdList = new ArrayList<>();
                paasFormDataEntityExtList.forEach(item -> spuIdList.add(item.getDataId()));
                //子产品数据
                boolQueryBuilder = boolQuery();
                boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
                boolQueryBuilder.filter(termsQuery(ProductEnum.getAttrConnectData(ProductEnum.PARENT_ID), spuIdList));
                boolQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
                List<PaasFormDataEntityExt> childProductList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_PRODUCT,boolQueryBuilder,PaasFormDataEntityExt.class,null);
                //分仓数据
                boolQueryBuilder = boolQuery();
                boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
                boolQueryBuilder.filter(termQuery(ProductWarehouseSubFormEnum.getEsAttr(ProductWarehouseSubFormEnum.WAREHOUSE_CHECKED), 1));
                boolQueryBuilder.filter(termQuery(StringConstant.DEL, DelEnum.NORMAL.getDel()));
                boolQueryBuilder.filter(termsQuery(ProductWarehouseSubFormEnum.getEsAttr(ProductWarehouseSubFormEnum.PARENT_ID), spuIdList));
                boolQueryBuilder.mustNot(termQuery(ProductWarehouseSubFormEnum.getEsAttr(ProductWarehouseSubFormEnum.WAREHOUSE_ID), 0));
                List<PaasFormDataEntity> productWarehouseEntityList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_PRODUCT_WAREHOUSE, boolQueryBuilder, PaasFormDataEntity.class, Arrays.asList(ProductWarehouseSubFormEnum.getAttrConnectData(ProductWarehouseSubFormEnum.WAREHOUSE_NAME), ProductWarehouseSubFormEnum.getAttrConnectData(ProductWarehouseSubFormEnum.WAREHOUSE_ID), ProductWarehouseSubFormEnum.getAttrConnectData(ProductWarehouseSubFormEnum.PRODUCT_ID), ProductWarehouseSubFormEnum.getAttrConnectData(ProductWarehouseSubFormEnum.PARENT_ID)));
                List<ProductWarehouseEntity> productWarehouseEntities = transferSubFormHelper.transferFormDataToProductWarehouseList(productWarehouseEntityList);

                Map<Long, Map<Long, String>> warehouseMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                Map<Long, Map<Long, String>> skuWarehouseMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                for (ProductWarehouseEntity entity : productWarehouseEntities) {
                    //父产品仓库
                    Map<Long, java.lang.String> map = warehouseMap.getOrDefault(entity.getParentId(), new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY));
                    map.put(entity.getWarehouseId(), entity.getWarehouseName());
                    warehouseMap.put(entity.getParentId(), map);
                    //子产品仓库
                    Map<Long, java.lang.String> map2 = skuWarehouseMap.getOrDefault(entity.getProductId(), new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY));
                    map2.put(entity.getWarehouseId(), entity.getWarehouseName());
                    skuWarehouseMap.put(entity.getProductId(), map2);
                }
                List<UpdateDataEntity> updateList = new ArrayList<>();
                for (PaasFormDataEntityExt entityExt : paasFormDataEntityExtList) {
                    Long spuId = entityExt.getDataId();
                    Map<Long, String> spuWarehouseMap = warehouseMap.getOrDefault(spuId, new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY));
                    JSONObject data = new JSONObject();
                    try {
                        data.put(ProductEnum.WAREHOUSE.getAttr(), Arrays.stream(spuWarehouseMap.keySet().toArray()).map(Object::toString).toArray(String[]::new));
                    }catch (Exception e){
                        e.printStackTrace();
                        throw new XbbException(SystemErrorCodeEnum.API_ERROR_100001);
                    }
                    data.put(ProductEnum.WAREHOUSE_LINK_TEXT.getAttr(), spuWarehouseMap.values().toArray());
                    updateList.add(ExplainUtil.getUpdateData(spuId, data, corpid));
                }
                for (PaasFormDataEntityExt entityExt : childProductList) {
                    Long skuId = entityExt.getDataId();
                    Map<Long, String> childWarehouseMap = skuWarehouseMap.getOrDefault(skuId, new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY));
                    JSONObject data = new JSONObject();
                    data.put(ProductEnum.WAREHOUSE.getAttr(), Arrays.stream(childWarehouseMap.keySet().toArray()).map(Object::toString).toArray(String[]::new));
                    data.put(ProductEnum.WAREHOUSE_LINK_TEXT.getAttr(), childWarehouseMap.values().toArray());
                    updateList.add(ExplainUtil.getUpdateData(skuId, data, corpid));
                }
                if (!updateList.isEmpty()) {
                    productModel.updateBatch(updateList, corpid);
                }
                LOG.warn(corpid + " : " + dataDataMark);
            }
        }
        LOG.warn("fixParentProductDataWarehouse success");
        LOG.warn("fixParentProductDataWarehouse time consume:" + (DateTimeUtil.getInt() - start));
        return null;
    }

    @RequestMapping(value = "/addUnitInfoToSupplierProduct", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String addUnitInfoToSupplierProduct(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        List<String> corpidList = companyModel.getCorpidList();
        int index = 1;
        for (String corpid : corpidList){
            LOG.warn("addUnitInfoToSupplierProduct " + corpid + ":" + index + "/" + corpidList.size());
            index++;
            Map<String,Object> param = new HashMap();
            param.put(ParameterConstant.CORPID, corpid);
            param.put(ParameterConstant.DEL, DelEnum.NORMAL.getDel());
            List<SupplierProductEntity> supplierProductEntities = supplierProductModel.findEntitys(param);
            if (supplierProductEntities.isEmpty()) {
                continue;
            }
            Long dataDataMark = 0L;
            List<PaasFormDataEntityExt> paasFormDataEntityExtList = new ArrayList<>();
            paasFormDataEntityExtList.add(new PaasFormDataEntityExt());
            while (!paasFormDataEntityExtList.isEmpty()) {
                //只要父产品数据
                BoolQueryBuilder boolQueryBuilder = boolQuery();
                boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
                boolQueryBuilder.filter(termQuery(ProductEnum.getEsAttr4Keyword(ProductEnum.PARENT_ID), 0));
                ListVO listVO = scriptEsHelper.list(boolQueryBuilder, 1000, PaasFormDataEntityExt.class, IndexTypeEnum.IDX_SAAS_PRODUCT, dataDataMark,Arrays.asList("id",FieldTypeEnum.DATAID.getAlias(),ProductEnum.getAttrConnectData(ProductEnum.UNIT)));
                paasFormDataEntityExtList = listVO.getList();
                dataDataMark = listVO.getDataIdMark();
                if (paasFormDataEntityExtList.isEmpty()) {
                    continue;
                }
                Map<Long,String> productUnitMap = new HashMap<>(paasFormDataEntityExtList.size());
                for (PaasFormDataEntityExt entityExt : paasFormDataEntityExtList) {
                    if (Objects.nonNull(entityExt.getData())) {
                        productUnitMap.put(entityExt.getDataId(),entityExt.getData().getString(ProductEnum.UNIT.getAttr()));
                    }else {
                        productUnitMap.put(entityExt.getDataId(),"");
                    }
                }
                for (SupplierProductEntity supplierProduct : supplierProductEntities) {
                    supplierProduct.setUnit(productUnitMap.getOrDefault(supplierProduct.getParentId(), ""));
                }
                supplierProductModel.updateBatch(supplierProductEntities,corpid);
                LOG.warn(corpid + " : " + dataDataMark);
            }
        }
        LOG.warn("addUnitInfoToSupplierProduct success");
        return null;
    }


    @RequestMapping(value = "/fixOutstockAddress", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String fixOutstockAddress(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        String corpid = fixDataJobDTO.getCorpid();
        PaasFormExplainEntity paasFormExplainEntity = paasFormExplainModel.getByBusinessType(XbbRefTypeEnum.CONTRACT_OUTSTOCK.getCode(),corpid);
        List<FieldAttrEntity> fieldAttrEntityList = JSONArray.parseArray(paasFormExplainEntity.getExplains(),FieldAttrEntity.class);
        for (FieldAttrEntity fieldAttrEntity : fieldAttrEntityList) {
            if (Objects.equals(fieldAttrEntity.getAttr(),ContractOutstockEnum.CUSTOMER_ADDRESS.getAttr()) && Objects.equals(fieldAttrEntity.getIsRedundant(),1)){
                fieldAttrEntity.setAttr("address_1");
                break;
            }
        }
        paasFormExplainEntity.setExplains(JSONArray.toJSONString(fieldAttrEntityList));
        paasFormExplainModel.update(paasFormExplainEntity);
        Map<String,Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put(StringConstant.CORPID,corpid);
        param.put(StringConstant.DEL,DelEnum.NORMAL.getDel());
        List<OutstockEntityExt> outstockEntityExtList = outstockModel.findEntitys(param);
        List<UpdateDataEntity> updateList = new ArrayList<>();
        JSONObject defaultAddress = new JSONObject();
        defaultAddress.put("address","");
        defaultAddress.put("province","");
        defaultAddress.put("city","");
        defaultAddress.put("district","");
        for (OutstockEntityExt outstockEntityExt : outstockEntityExtList) {
            if (Objects.equals(outstockEntityExt.getData().getInteger(OutstockEnum.TYPE.getAttr()), OutstockTypeEnum.CONTRACT_OUTSTOCK.getCode())){
                JSONObject data = outstockEntityExt.getData();
                JSONObject address;
                try {
                    address = outstockEntityExt.getData().getJSONObject(ContractOutstockEnum.CUSTOMER_ADDRESS.getAttr());
                    if (!address.containsKey("address")){
                        address.put("address","");
                    }
                    if (!address.containsKey("province")){
                        address.put("province","");
                    }
                    if (!address.containsKey("city")){
                        address.put("city","");
                    }
                    if (!address.containsKey("district")){
                        address.put("district","");
                    }
                }catch (Exception e){
                    address = defaultAddress;
                }
                data.put("address_1",address);
                data.put(ContractOutstockEnum.CUSTOMER_ADDRESS.getAttr(),defaultAddress);
                outstockModel.update(outstockEntityExt);

            }
        }
        LOG.warn("fixOutstockAddress success");
        return null;
    }

    @RequestMapping(value = "/fixPaasFormSerialNo", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String fixPaasFormSerialNo(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        List<String> corpidList = companyModel.getCorpidList();
        int index = 1;
        List<PaasFormEntityExt> updateList = new ArrayList<>(150);
        for (String corpid : corpidList) {
            LOG.warn("fixPaasFormSerialNo:" + index + "/" + corpidList.size());
            index++;
            boolean needUpdate =false;
            Map<String,Object> map = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            map.put("corpid",corpid);
            map.put("del",0);
            map.put("businessType",XbbRefTypeEnum.PRODUCT.getCode());
            List<PaasFormEntityExt> formList = paasFormModel.findEntitys(map);
            if (!formList.isEmpty()) {
                for (PaasFormEntityExt item : formList) {
                    List<SummaryDataPoJo> customTitles = JSON.parseArray(item.getCustomTitle(), SummaryDataPoJo.class);
                    List<SummaryDataPoJo> summarys = JSON.parseArray(item.getSummary(), SummaryDataPoJo.class);
                    List<SummaryDataPoJo> labels = JSON.parseArray(item.getLabels(), SummaryDataPoJo.class);
                    if (Objects.nonNull(customTitles)) {
                        Iterator<SummaryDataPoJo> customIterator = customTitles.iterator();
                        while (customIterator.hasNext()) {
                            SummaryDataPoJo summaryDataPoJo = customIterator.next();
                            if (Objects.equals(summaryDataPoJo.getAttr(), "text_2")) {
                                summaryDataPoJo.setAttr(ProductEnum.SERIALNO.getAttr());
                                item.setCustomTitle(JSONArray.toJSONString(customTitles));
                                needUpdate = true;
                                break;
                            }
                        }
                    }
                    if (Objects.nonNull(summarys)) {
                        Iterator<SummaryDataPoJo> summaryIterator = summarys.iterator();
                        while (summaryIterator.hasNext()) {
                            SummaryDataPoJo summaryDataPoJo = summaryIterator.next();
                            if (Objects.equals(summaryDataPoJo.getAttr(), "text_2")) {
                                summaryDataPoJo.setAttr(ProductEnum.SERIALNO.getAttr());
                                summaryDataPoJo.setFieldType(ProductEnum.SERIALNO.getFieldType());
                                item.setSummary(JSONArray.toJSONString(summarys));
                                needUpdate = true;
                                break;
                            }
                        }
                    }
                    if (Objects.nonNull(labels)) {
                        Iterator<SummaryDataPoJo> labelIterator = labels.iterator();
                        while (labelIterator.hasNext()) {
                            SummaryDataPoJo summaryDataPoJo = labelIterator.next();
                            if (Objects.equals(summaryDataPoJo.getAttr(), "text_2")) {
                                summaryDataPoJo.setAttr(ProductEnum.SERIALNO.getAttr());
                                summaryDataPoJo.setFieldType(ProductEnum.SERIALNO.getFieldType());
                                item.setLabels(JSONArray.toJSONString(labels));
                                needUpdate = true;
                                break;
                            }
                        }
                    }
                    if (needUpdate) {
                        updateList.add(item);
                    }
                }
            }
            if (updateList.size()>20) {
                paasFormModel.updateBatchTemp(updateList);
                updateList.clear();
            }
        }
        if (!updateList.isEmpty()) {
            paasFormModel.updateBatchTemp(updateList);
        }
        LOG.warn("fixPaasFormSerialNo over");
        return null;
    }

    /**
     * 修复合同金额相关数据，如已收、未收、坏账等
     * @param formDataUpdateGetDTO 更新数据dto
     * @param contractId 合同id
     * @param corpid 公司id
     * @param contract 合同实体
     * @throws XbbException
     * @author 饶龙、陈山
     * @since v1.0
     * @version v1.0
     * @update 2020/3/18 by zcp 优化使其更新时能同时update几个字段，而非执行一次处理一个字段
     */
    private void fixContractAmount(FormDataUpdateGetDTO formDataUpdateGetDTO, Long contractId, String corpid, ContractEntityExt contract) throws XbbException {
        //正常回款单金额
        Double totalWriteOffAmount = fundMoneyHelp.getSheetTotalWriteOffAmount(XbbRefTypeEnum.PAYMENT_SHEET,formDataUpdateGetDTO,true,true,PaymentSheetEnum.CONTRACT.getAttr());
        //(负的)红冲回款单金额
        Double redAmount = fundMoneyHelp.getSheetRedAndBadAmount(XbbRefTypeEnum.PAYMENT_SHEET,formDataUpdateGetDTO, true, false, PaymentSheetEnum.CONTRACT.getAttr());
        //坏账金额
        Double badAmount = fundMoneyHelp.getSheetRedAndBadAmount(XbbRefTypeEnum.PAYMENT_SHEET,formDataUpdateGetDTO, false, true, PaymentSheetEnum.CONTRACT.getAttr());
        LOG.info("统计出来的金额为：totalWriteOffAmount："+ totalWriteOffAmount+"，redAmount："+redAmount+"，badAmount："+badAmount);

        List<UpdateDataEntity> updateDataEntityList = new ArrayList<>();

        Double finishedMoney = contract.getData().getDouble(ContractEnum.FINISH_AMOUNT.getAttr());
        Double unFinishedMoney = contract.getData().getDouble(ContractEnum.UN_FINISH_AMOUNT.getAttr());
        Double payPercent = contract.getData().getDouble(ContractEnum.PAY_PERCENT.getAttr());
        Double contractAmount = contract.getData().getDouble(ContractEnum.AMOUNT.getAttr());
        Double badMoney = contract.getData().getDouble(ContractEnum.BAD_AMOUNT.getAttr());
        // 正确的合同已收款
        Double rightFinished = Arith.add(totalWriteOffAmount, redAmount);
        // 正确的合同未收款
        /*
         * 合同金额=正常回款单金额-(正的)红冲回款单金额(实际入库的红冲金额是负数)+坏账金额+未收款金额
         * 即 合同金额=正常回款单金额+(负的)红冲回款单金额+坏账金额+未收款金额
         *
         * 未收款金额 = 合同金额 - ( 正常回款单金额+(负的)红冲回款单金额+坏账金额 ) = 合同金额 - 正常回款单金额 - (负的)红冲单金额 - 坏账金额
         */
        Double rightUnFinished = Arith.sub(Arith.sub(Arith.sub(contractAmount, totalWriteOffAmount),redAmount),badAmount);
        // 正确的合同收款比率
        Double rightPayPercent = 1D;
        if (Double.compare(contractAmount, 0) != 0) {
            rightPayPercent = Arith.div(rightFinished, contractAmount);
        }
        JSONObject updateData = new JSONObject();
        if (!Objects.equals(finishedMoney, rightFinished)) {
            updateData.put(ContractEnum.FINISH_AMOUNT.getAttr(), rightFinished);
        }
        if (!Objects.equals(unFinishedMoney, rightUnFinished)) {
            updateData.put(ContractEnum.UN_FINISH_AMOUNT.getAttr(), rightUnFinished);
        }
        if (!Objects.equals(payPercent, rightPayPercent)) {
            updateData.put(ContractEnum.PAY_PERCENT.getAttr(), rightPayPercent);
        }
        if (!Objects.equals(badMoney, badAmount)) {
            updateData.put(ContractEnum.BAD_AMOUNT.getAttr(), badAmount);
        }
        if (!updateData.isEmpty()) {
            updateDataEntityList.add(ExplainUtil.getUpdateData(contractId, updateData, corpid));
            contractModel.updateBatch(updateDataEntityList, corpid);
        }
    }

    /**
     * 修复应收款金额相关数据，如已收、未收、坏账等
     * @param formDataUpdateGetDTO 更新数据dto
     * @param paymentId 应收款id
     * @param corpid 公司id
     * @param payment 应收款实体
     * @throws XbbException
     * @author 饶龙、陈山
     * @since v1.0
     * @version v1.0
     * @update 2020/3/18 by zcp 优化使其更新时能同时update几个字段，而非执行一次处理一个字段
     */
    private void fixPaymentAmount(FormDataUpdateGetDTO formDataUpdateGetDTO, Long paymentId, String corpid, PaymentEntityExt payment) throws XbbException {
        //正常回款单金额
        Double totalWriteOffAmount = fundMoneyHelp.getSheetTotalWriteOffAmount(XbbRefTypeEnum.PAYMENT_SHEET,formDataUpdateGetDTO,true,true,PaymentSheetEnum.PAYMENT.getAttr());
        //(负的)红冲回款单金额
        Double redSheetAmount = fundMoneyHelp.getSheetRedAndBadAmount(XbbRefTypeEnum.PAYMENT_SHEET,formDataUpdateGetDTO, true, false, PaymentSheetEnum.PAYMENT.getAttr());
        //坏账金额
        Double badAmount = fundMoneyHelp.getSheetRedAndBadAmount(XbbRefTypeEnum.PAYMENT_SHEET,formDataUpdateGetDTO, false, true, PaymentSheetEnum.PAYMENT.getAttr());
        //该应收款关联的红冲应收金额
        Double redPaymentAmount = fundMoneyHelp.getRedPaymentAmount(payment, formDataUpdateGetDTO);

        List<UpdateDataEntity> updateDataEntityList = new ArrayList<>();
        Double planAmount = payment.getData().getDouble(PaymentEnum.AMOUNT.getAttr());
        Double finishedMoney = payment.getData().getDouble(PaymentEnum.REAL_AMOUNT.getAttr());
        Double unFinishedMoney = payment.getData().getDouble(PaymentEnum.UN_AMOUNT.getAttr());
        Double badMoney = payment.getData().getDouble(PaymentEnum.BAD_AMOUNT.getAttr());
        Double redMoney = payment.getData().getDouble(PaymentEnum.RED_AMOUNT.getAttr());
        String planStatus = payment.getData().getString(PaymentEnum.STATUS.getAttr());
        /*
         资金3.0对应收款增加了红冲应收款的功能，原单增加了红冲应收款字段，未收金额计算公式及状态判断规则有变化
         实收金额（不变） = 【回款单】核销金额（已核销-红冲已核销+预收款核销-红冲预收款核销）
         未收金额（有变化） = 应收款-实收金额-坏账金额-丨红冲应收丨
         坏账金额（不变）=【回款单】核销金额(已坏账)
         红冲应收金额（新增的字段）=【红冲应收单】"红冲应收金额"
         */
        // 正确的应收款已收款
        Double rightFinished = Arith.add(totalWriteOffAmount, redSheetAmount);
        //"应收款"-丨"红冲应收"丨。由于红冲应收为负数，所以直接用add
        Double leftAmount = Arith.add(planAmount, redPaymentAmount);
        Double rightUnFinished = Arith.sub(Arith.sub(Arith.sub(leftAmount, totalWriteOffAmount),redSheetAmount),badAmount);
        JSONObject jsonObject = new JSONObject();
        if (!Objects.equals(finishedMoney, rightFinished)) {
            jsonObject.put(PaymentEnum.REAL_AMOUNT.getAttr(), rightFinished);
        }
        if (!Objects.equals(unFinishedMoney, rightUnFinished)) {
            jsonObject.put(PaymentEnum.UN_AMOUNT.getAttr(), rightUnFinished);
        }
        if (!Objects.equals(badMoney, badAmount)) {
            jsonObject.put(PaymentEnum.BAD_AMOUNT.getAttr(), badAmount);
        }
        if (!Objects.equals(redMoney, redPaymentAmount)) {
            jsonObject.put(PaymentEnum.RED_AMOUNT.getAttr(), redPaymentAmount);
        }
        String rightPlanStatus = payAndPaymentSheetHelp.handleStatus(planAmount, rightUnFinished, badAmount, redPaymentAmount);
        if (!Objects.equals(planStatus, rightPlanStatus)) {
            jsonObject.put(PaymentEnum.STATUS.getAttr(), rightPlanStatus);
        }
        if (!jsonObject.isEmpty()) {
            updateDataEntityList.add(ExplainUtil.getUpdateData(paymentId, jsonObject, corpid));
            paymentModel.updateBatch(updateDataEntityList, corpid);
        }
    }


    @RequestMapping(value = "/fixBusinessUid", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String fixBusinessUid(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        Map<String, Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put("type", SoukeMealEnum.BUSINESS.getType());
        param.put("del", DelEnum.NORMAL.getDel());
        int index = 1;
        List<SearchCustomerCompanyEntity> companyList = searchCustomerCompanyModel.findEntitys(param).stream().filter(entity-> StringUtil.isEmpty(entity.getUid())).collect(Collectors.toList());
        for (SearchCustomerCompanyEntity item : companyList) {
            String corpid = item.getCorpid();
            JSONObject jsonObject = new JSONObject();
            jsonObject.put("corpid", corpid);
            jsonObject.put("userId",item.getUserId());
            jsonObject.put("platform","web");
            jsonObject.put("user_id",item.getUserId());
            jsonObject.put("uid", corpid);
            jsonObject.put("username", item.getUsername());
            // 开通账号为主账号
            jsonObject.put("role", "mainaccount");
            jsonObject.put("company_name", item.getCompanyName());
            jsonObject.put("expiry_time", item.getExtraExpiry());
            JSONArray array = new JSONArray();
            JSONObject obj = new JSONObject();
            obj.put("type", "匿名套餐");
            array.add(obj);
            jsonObject.put("meals", array);
            SearchCustomerDTO searchCustomerDTO = JSONObject.toJavaObject(jsonObject, SearchCustomerDTO.class);
            try {
                searchCustomerServiceImpl.sendRegister(searchCustomerDTO);
                LOG.info("第" + index + "条更新完成！");
                index ++;
            } catch (XbbException e) {
                LOG.error("更新的第" + index + "条出错，corpid = " + corpid);
            }
            item.setUid(corpid);
        }
        searchCustomerCompanyModel.updateBatch(companyList);

        LOG.info("fixBusinessUid success");
        return null;
    }

    @RequestMapping(value = "/fixWorkOrderExplain", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String fixWorkOrderExplain(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        long start = 0L;
        Map<String,Object> param = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        param.put(StringConstant.DEL,DelEnum.NORMAL.getDel());
        param.put("addtimeGte",1584288000);
        List<WorkOrderExplainEntity> paasFormExplainEntityList = workOrderExplainModel.findEntitys(param);
        int index = 0;
        List<String> nullIdList = new ArrayList<>();
        for (WorkOrderExplainEntity paasFormExplainEntity : paasFormExplainEntityList) {
            index++;
            LOG.warn(index + "/" + paasFormExplainEntityList.size());
            List<FieldAttrEntity> explainList = JSONArray.parseArray(paasFormExplainEntity.getExplains(),FieldAttrEntity.class);
            for (FieldAttrEntity fieldAttrEntity : explainList) {
                if (Objects.equals(fieldAttrEntity.getAttr(),WorkOrderEnum.SPARE_PARTS.getAttr())){
                    if (Objects.isNull(fieldAttrEntity.getSubForm()) || Objects.isNull(fieldAttrEntity.getSubForm().getItems())){
                        nullIdList.add(paasFormExplainEntity.getCorpid() + "_" + paasFormExplainEntity.getId());
                        continue;
                    }
                    List<? extends FieldAttrEntity> subItem = fieldAttrEntity.getSubForm().getItems();
                    for (FieldAttrEntity entity : subItem) {
                        if (Objects.equals(entity.getIsRedundant(),0)){
                            entity.setIsForbidden(0);
                        }
                    }
                    fieldAttrEntity.getSubForm().setItems(subItem);
                    break;
                }
            }
            paasFormExplainEntity.setExplains(JSONArray.toJSONString(explainList));
            workOrderExplainModel.update(paasFormExplainEntity);
        }
        LOG.warn("nullIdList:" + JSONArray.toJSONString(nullIdList));
        LOG.warn("consume:" + (DateTimeUtil.getInt() - start));
        return "success";
    }

    /**
     * 处理表单字段默认名称
     */
    @RequestMapping(value = "/fixFormFieldDefaultName", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String fixFormFieldDefaultName(@RequestBody @Valid FixFormDTO fixFormDTO, BindingResult br) {
        XbbResponse<ScriptVO> response;
        if (br.hasErrors()) {
            String errMsg = Objects.requireNonNull(br.getFieldError()).getDefaultMessage();
            response = new XbbResponse<>(SystemErrorCodeEnum.API_ERROR_100002, errMsg);
        } else {
            try {
                ScriptVO scriptVO = repairExplainService.fixFormFieldDefaultName(fixFormDTO);
                response = new XbbResponse<>(scriptVO);
            } catch (XbbException e) {
                response = new XbbResponse<>(e);
            }
        }
        return JSON.toJSONString(response);
    }

    /**
     * 处理表单字段默认名称
     */
    @RequestMapping(value = "/fixWorkReportExplain", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String fixWorkReportExplain(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws XbbException {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        long start = DateTimeUtil.getInt();
        List<String> corpidList;
        if (Objects.isNull(fixDataJobDTO.getCorpidList()) || fixDataJobDTO.getCorpidList().isEmpty()) {
            corpidList = companyModel.getCorpidList();
        } else {
            corpidList = fixDataJobDTO.getCorpidList();
        }
        List<Integer> businessTypeList = Arrays.asList(XbbRefTypeEnum.WORKREPORT_DAILY.getCode(),XbbRefTypeEnum.WORKREPORT_WEEKLY.getCode(),XbbRefTypeEnum.WORKREPORT_MONTHLY.getCode());
        Integer index = 0;
        for (String corpid : corpidList) {
            index++;
            LOG.warn("corpid:" + index + "/" + corpidList.size());
            List<PaasFormExplainEntity> list = paasFormExplainModel.getListForUpdateProduct(corpid,businessTypeList);
            for (PaasFormExplainEntity explainEntity : list) {
                List<FieldAttrEntity> fieldAttrEntityList = JSONArray.parseArray(explainEntity.getExplains(),FieldAttrEntity.class);
                for (FieldAttrEntity fieldAttrEntity : fieldAttrEntityList) {
                    if (Objects.equals(fieldAttrEntity.getAttr(), WorkReportFieldEnum.TYPE.getAttr())) {
                        fieldAttrEntity.setEditForbidden(0);
                        fieldAttrEntity.setAdvancedSetHide(1);
                        fieldAttrEntity.setVisibleScopeEnable(0);
                        fieldAttrEntity.setEditableAdvanceEnable(0);
                        break;
                    }
                }
                explainEntity.setExplains(JSONArray.toJSONString(fieldAttrEntityList));
                paasFormExplainModel.update(explainEntity);
            }
        }
        LOG.warn("consume:" + (DateTimeUtil.getInt() - start));
        LOG.warn("over");
        return "sucess";
    }

    /**
     * 修复合同成本/毛利计算规则
     * 只允许单个公司刷脚本，或者单条合同刷数据(数据源以退货退款为主，主要是查询数据少)
     */
    @RequestMapping(value = "/fixContractCost", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String fixContractCost(@RequestBody @Valid FixDataJobDTO fixDataJobDTO, BindingResult br) throws XbbException {
        if (!proBaseConfig.getXbbCode().equals(fixDataJobDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        long start = DateTimeUtil.getInt();

        String corpid = fixDataJobDTO.getCorpid();

        Boolean isJxcUse = paasAppService.validateAppEnable(null, XbbRefTypeEnum.JXC.getAlias(), SaasMarkEnum.SAAS.getCode(), corpid);

        // 这个数值传合同id
        Long fixContractId = fixDataJobDTO.getDataId();
        // 查询出所有的退货退款
        BoolQueryBuilder refundQueryBuilder = boolQuery();
        refundQueryBuilder.filter(termQuery("corpid.keyword", corpid));
        if(fixContractId != null){
            refundQueryBuilder.filter(termQuery(RefundEnum.getEsAttr4Keyword(RefundEnum.CONTRACT_ID), fixContractId));
        }
        refundQueryBuilder.filter(termQuery("del", DelEnum.NORMAL.getDel()));
        refundQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD, IndexTypeEnum.IDX_SAAS_REFUND.getType()));
        SearchSourceBuilder refundBuilder = new SearchSourceBuilder();
        refundBuilder.query(refundQueryBuilder);
        PageRequest refundRequest = EsUtil.setPage(refundBuilder, 1, PaasConstant.ES_MAX_PAGE_SIZE);
        SearchRequest refundSearchRequest = new SearchRequest(IndexTypeEnum.IDX_SAAS_REFUND.getIndex());
        refundSearchRequest.source(refundBuilder);
        XbbAggregatedPage<RefundEntityExt> refundEntities = xbbElasticsearchRestTemplate.queryForPages(refundRequest,refundSearchRequest,RefundEntityExt.class);

        List<Long> redContractIdIn = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        List<Long> oldContractIdIn = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        // 合同与红冲合同对应map
        Map<Long, List<Long>> contractIdAndRedContractMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        // 合同与入库单对应map
        Map<Long, List<Long>> contractIdAndInstockIdMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        // 查询出所有关联原合同的退货金额
        Map<Long, Double> allContractCostMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);

        for (RefundEntityExt item : refundEntities.getContent()) {
            JSONObject itemData = item.getData();
            Long redConId = itemData.getLong(RefundEnum.RED_CONTRACT_ID.getAttr());
            redContractIdIn.add(redConId);
            Long oldConId = FastJsonHelper.getLongOrDefaultFromFormData(itemData, RefundEnum.CONTRACT_ID.getAttr(), 0L);
            oldContractIdIn.add(oldConId);

            // 合同与红冲合同对应关系
            if(contractIdAndRedContractMap.containsKey(oldConId)){
                List<Long> redConIdList = contractIdAndRedContractMap.get(oldConId) == null ? new ArrayList<>() : contractIdAndRedContractMap.get(oldConId);
                List<Long> idList = new ArrayList<>(redConIdList);
                idList.add(redConId);
                contractIdAndRedContractMap.put(oldConId, idList);
            } else {
                contractIdAndRedContractMap.put(oldConId, Arrays.asList(redConId));
            }

            // 合同与入库单对应关系
            JSONArray instockIdArr = FastJsonHelper.getJsonArrOrDefaultFromFormData(itemData, RefundEnum.INSTOCK_ID.getAttr(), new JSONArray());
            if(!instockIdArr.isEmpty()){
                List<Long> instocks = instockIdArr.toJavaList(Long.class);
                if(contractIdAndInstockIdMap.containsKey(oldConId)){
                    List<Long> instockList = contractIdAndInstockIdMap.get(oldConId) == null ? new ArrayList<>() : contractIdAndInstockIdMap.get(oldConId);
                    List<Long> idList = new ArrayList<>(instockList);
                    idList.addAll(instocks);
                    contractIdAndInstockIdMap.put(oldConId, idList);
                } else {
                    contractIdAndInstockIdMap.put(oldConId, instocks);
                }
            }

            // 统计所有的退货金额
            Double returnCost = FastJsonHelper.getDoubleOrDefaultFromFormData(itemData, RefundEnum.RETURN_AMOUNT.getAttr(), 0D);
            if(allContractCostMap.containsKey(oldConId)){
                Double cost = allContractCostMap.get(oldConId) == null ? 0D : allContractCostMap.get(oldConId);
                returnCost = Arith.add(returnCost, cost);
                allContractCostMap.put(oldConId, returnCost);
            } else {
                allContractCostMap.put(oldConId, returnCost);
            }
        }

        // 查询出所有关联原合同的出库单
        Map<Long, List<Long>> allContractOutMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        // 所有对应的合同实体
        List<ContractEntityExt> contractList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        List<Long> contractIdList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        BoolQueryBuilder entityQueryBuilder = boolQuery();
        entityQueryBuilder.filter(termQuery("corpid.keyword", corpid));
        entityQueryBuilder.filter(termsQuery(FieldTypeEnum.DATAID.getAlias(), oldContractIdIn));
        entityQueryBuilder.filter(termQuery("del", 0));
        entityQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD, IndexTypeEnum.IDX_SAAS_CONTRACT.getType()));
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.query(entityQueryBuilder);
        PageRequest pageRequest = EsUtil.setPage(sourceBuilder, 1, PaasConstant.ES_MAX_PAGE_SIZE);
        SearchRequest searchRequest = new SearchRequest(IndexTypeEnum.IDX_SAAS_CONTRACT.getIndex());
        searchRequest.source(sourceBuilder);
        XbbAggregatedPage<ContractEntityExt> esEntities = xbbElasticsearchRestTemplate.queryForPages(pageRequest, searchRequest, ContractEntityExt.class);
        for (ContractEntityExt entity : esEntities.getContent()) {
            Long contractId = entity.getDataId();
            contractList.add(entity);
            contractIdList.add(contractId);

            JSONObject data = entity.getData();
            List<Long> outstockIdList = FastJsonHelper.getJsonArrOrDefaultFromFormData(data, ContractEnum.OUTSTOCK_ID.getAttr(), new JSONArray()).toJavaList(Long.class);

            if(allContractOutMap.containsKey(contractId)){
                List<Long> outIdList = allContractOutMap.get(contractId) == null ? new ArrayList<>() : allContractOutMap.get(contractId);
                List<Long> outIdIn = new ArrayList<>(outIdList);
                outIdIn.addAll(outstockIdList);
                allContractOutMap.put(contractId, outIdIn);
            } else {
                allContractOutMap.put(contractId, outstockIdList);
            }
        }

        Map<Long, Double> contractCostMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        Map<Long, Map<Long, Double>> instockProductIdAndNumMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for(Long contractId : oldContractIdIn){
            Double jxc2UpdateInstockCost = BasicConstant.ZERO_DOUBLE;
            // 查询该合同对应所有入库单的产品
            List<Long> instockList = contractIdAndInstockIdMap.get(contractId) == null ? new ArrayList<>() : contractIdAndInstockIdMap.get(contractId);
            //入库单的产品id及其数量
            Map<Long, Double> instockProductIdAndNum = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            if(!instockList.isEmpty()){
                Map<String,Object> instockProductParam = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                instockProductParam.put("corpid", corpid);
                instockProductParam.put("instockIdIn",instockList);
                instockProductParam.put("del", 0);
                List<InstockProductEntity> instockProductEntityList = instockProductService.findEntitys(instockProductParam);
                for(InstockProductEntity instockPro : instockProductEntityList){
                    // 新数据计算，直接计算所有该合同所有入库单的成本
                    Double productNum = instockPro.getProductNum() == null ? 0D : Math.abs(instockPro.getProductNum());
                    Double productCost = instockPro.getCost() == null ? 0D : instockPro.getCost();
                    jxc2UpdateInstockCost = Arith.add(jxc2UpdateInstockCost, Arith.mul(productNum, productCost));

                    // 统计入库单每一件产品的数量
                    Long productId = instockPro.getProductId();
                    Double num = instockPro.getProductNum();
                    if(instockProductIdAndNum.containsKey(productId)){
                        Double inNum = instockProductIdAndNum.get(productId) == null ? BasicConstant.ZERO_DOUBLE : instockProductIdAndNum.get(productId);
                        Double countNum = Arith.add(inNum, num);
                        instockProductIdAndNum.put(productId, countNum);
                    } else {
                        instockProductIdAndNum.put(productId, num);
                    }
                }

                contractCostMap.put(contractId, jxc2UpdateInstockCost);
                instockProductIdAndNumMap.put(contractId, instockProductIdAndNum);
            }
        }

        // 合同与红冲合同退货产品成本对应map
        Map<Long, Double> contractIdAndCostMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);

        Iterator entries = contractIdAndRedContractMap.entrySet().iterator();
        while(entries.hasNext()){
            Map.Entry entry = (Map.Entry) entries.next();
            Long key = (Long) entry.getKey();
            List<Long> redConIdList = contractIdAndRedContractMap.get(key);
            Double costAmount = BasicConstant.ZERO_DOUBLE;
            if(redConIdList.size() > 0) {
                Map<Long, Double> productIdAndNumMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                Map<String,Object> redParam = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                redParam.put("corpid", corpid);
                redParam.put("contractIdIn",redConIdList);
                redParam.put("del", 0);
                // 拿到红冲合同的所有产品
                List<ContractProductEntity> contractProductEntityList = contractProductModel.findEntitys(redParam);

                //判断是否是新旧数据
                boolean sourceDoc = false;
                for(ContractProductEntity entity : contractProductEntityList){
                    JSONObject data = entity.getData();
                    if (data.containsKey(SelectProductEnum.SOURCE_DOC.getAttr())) {
                        sourceDoc = true;
                        break;
                    }
                }
                // 新数据直接使用累加结果
                if(sourceDoc){
                    Double inCost = contractCostMap.get(key) == null ? BasicConstant.ZERO_DOUBLE : contractCostMap.get(key);
                    contractIdAndCostMap.put(key, inCost);
                    break;
                }

                //-----------------------旧数据处理---------------------------
                // 退货产品ID以及对应的数量
                for(ContractProductEntity entity : contractProductEntityList){
                    Long pageProductId = entity.getProductId();
                    Double productNum = entity.getProductNum() == null ? 0D : Math.abs(entity.getProductNum());
                    if(productIdAndNumMap.containsKey(pageProductId)){
                        Double num = productIdAndNumMap.get(pageProductId) == null ? 0D : productIdAndNumMap.get(pageProductId);
                        productNum = Arith.add(productNum, num);
                    }
                    productIdAndNumMap.put(pageProductId, productNum);
                }
                List<Long> outstockIdList = allContractOutMap.get(key);
                Map<Long, Double> instockProductIdAndNum = instockProductIdAndNumMap.get(key);
                if(outstockIdList != null && !instockProductIdAndNum.isEmpty() && isJxcUse){
                    Map<String,Object> outstockParam = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    outstockParam.put("corpid", corpid);
                    outstockParam.put("del", DelEnum.NORMAL.getDel());
                    outstockParam.put("outstockIdIn", outstockIdList);
                    List<OutstockProductEntity> outstockProductList = outstockProductModel.findEntitys(outstockParam);
                    Map<Long, OutstockProductEntity> outstockProductEntityMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    // 算出每个产品对应的成本
                    Map<Long, Double> productIdAndCost = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    // 所有的出库记录
                    for (OutstockProductEntity outstockProductEntity : outstockProductList) {
                        Long productId = outstockProductEntity.getProductId();
                        Double productNum = outstockProductEntity.getProductNum() == null ? 0D : outstockProductEntity.getProductNum();
                        Double productCost = outstockProductEntity.getCost() == null ? 0D : outstockProductEntity.getCost();
                        // 将所有记录的相同产品的平均成本求出
                        if (outstockProductEntityMap.containsKey(productId)) {
                            OutstockProductEntity oldOutstockProductEntity = outstockProductEntityMap.get(productId);
                            Double oldProductNum = oldOutstockProductEntity.getProductNum() == null ? 0D : oldOutstockProductEntity.getProductNum();
                            Double oldProductCost = oldOutstockProductEntity.getCost() == null ? 0D : oldOutstockProductEntity.getCost();
                            // 上一次的产品总成本
                            Double oldCost = Arith.mul(oldProductNum, oldProductCost);
                            // 这一次的产品总成本
                            Double newCost = Arith.mul(productNum, productCost);
                            // (上一次的产品总成本+这一次的产品总成本)/两次的总数量
                            productCost = Arith.div(Arith.add(oldCost, newCost), Arith.add(oldProductNum, productNum), 2);
                        }
                        outstockProductEntityMap.put(productId, outstockProductEntity);
                        productIdAndCost.put(productId, productCost);
                    }
                    // 遍历红冲合同
                    Iterator iterator = instockProductIdAndNum.keySet().iterator();
                    while (iterator.hasNext()) {
                        Long id = Long.valueOf(iterator.next().toString());
                        Double productNum = instockProductIdAndNum.get(id);
                        if(productIdAndCost.containsKey(id)){
                            costAmount = Arith.add(costAmount, Arith.mul(productNum, productIdAndCost.get(id)));
                        }
                    }
                } else if(!isJxcUse){
                    // 不开启进销存是直接查询原合同关联产品表的成本*红冲合同产品表的产品数量(退货产品数量)
                    BoolQueryBuilder boolQueryBuilder = boolQuery();
                    boolQueryBuilder.filter(termQuery("corpid.keyword",corpid));
                    boolQueryBuilder.filter(termQuery(StringConstant.DEL,DelEnum.NORMAL.getDel()));
                    boolQueryBuilder.filter(termQuery(ContractProductSubFormEnum.getEsAttr(ContractProductSubFormEnum.TYPE),201));
                    boolQueryBuilder.filter(termQuery(ContractProductSubFormEnum.getEsAttr(ContractProductSubFormEnum.CONTRACT_ID), key));
                    boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD, IndexTypeEnum.IDX_SAAS_CONTRACT_PRODUCT.getType()));
                    List<String> fieldList = Arrays.asList(ContractProductSubFormEnum.getAttrConnectData(ContractProductSubFormEnum.PRODUCT_ID), ContractProductSubFormEnum.getAttrConnectData(ContractProductSubFormEnum.CONTRACT_ID), ContractProductSubFormEnum.getAttrConnectData(ContractProductSubFormEnum.PRODUCT_NUM), ContractProductSubFormEnum.getAttrConnectData(ContractProductSubFormEnum.PRICE), ContractProductSubFormEnum.getAttrConnectData(ContractProductSubFormEnum.COST));
                    List<PaasFormDataEntity> list =  esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_CONTRACT_PRODUCT,boolQueryBuilder, PaasFormDataEntity.class, fieldList);
                    if(list.size() > 0) {
                        List<ContractProductEntity> contractProductEntities = transferSubFormHelper.transferFormDataToContractProductList(list);
                        for (ContractProductEntity contractProductEntity : contractProductEntities) {
                            Long productId = contractProductEntity.getProductId();
                            Double cost = contractProductEntity.getCost() == null ? 0D : contractProductEntity.getCost();
                            if(productIdAndNumMap.containsKey(productId)){
                                Double productCost = Arith.mul(cost, productIdAndNumMap.get(productId));
                                costAmount = Arith.add(costAmount, productCost);
                            }
                        }
                    }
                }
            }
            contractIdAndCostMap.put(key, costAmount);
        }

        BoolQueryBuilder boolQueryBuilder = boolQuery();
        boolQueryBuilder.filter(termQuery("corpid.keyword", corpid));
        boolQueryBuilder.filter(termQuery("del", 0));
        boolQueryBuilder.filter(termQuery("data." + OutstockEnum.TYPE.getAttr(), OutstockTypeEnum.CONTRACT_OUTSTOCK.getCode()));
        boolQueryBuilder.filter(termsQuery("data." + OutstockEnum.REF_ID.getAttr(), oldContractIdIn));
        boolQueryBuilder.filter(termsQuery("flowStatus", Arrays.asList(FlowStatusEnum.NOT_NEED_APPROVAL.getType(), FlowStatusEnum.PASS.getType())));
        boolQueryBuilder.filter(termQuery(ElasticConstant.MY_JOIN_FIELD, IndexTypeEnum.IDX_SAAS_OUTSTOCK.getType()));
        List<PaasFormDataEntityExt> outstockList = esHelper.findByScroll(IndexTypeEnum.IDX_SAAS_OUTSTOCK, boolQueryBuilder, PaasFormDataEntityExt.class, Arrays.asList(OutstockEnum.getAttrConnectData(OutstockEnum.REF_ID), FieldTypeEnum.DATAID.getAlias()));

        // 根据出库单获取对应的产品
        List<Long> dataIdIn = new ArrayList<>();
        outstockList.forEach(outstock -> dataIdIn.add(outstock.getDataId()));
        Map<String, Object> outstockParam = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        outstockParam.put("corpid", corpid);
        outstockParam.put("del", 0);
        outstockParam.put("outstockIdIn", dataIdIn);
        List<OutstockProductEntity> outstockAllProductList = outstockProductModel.findEntitys(outstockParam);

        // 合同和关联的出库单的对应关系
        Map<Long, List<Long>> contractOutstockMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (ContractEntityExt contractEntity : contractList) {
            Long contractId = contractEntity.getId();
            List<Long> outstockIdList = contractOutstockMap.get(contractId);
            if (outstockIdList == null) {
                outstockIdList = new ArrayList<>();
            }
            for (PaasFormDataEntityExt outstock : outstockList) {
                Long refId = outstock.getData().getLong(OutstockEnum.REF_ID.getAttr());
                if (Objects.equals(contractId, refId)) {
                    outstockIdList.add(outstock.getDataId());
                }
            }
            contractOutstockMap.put(contractId, outstockIdList);
        }

        // 合同和出库产品的对应关系
        Map<Long, List<OutstockProductEntity>> contractOutstockProductMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (ContractEntityExt contractEntity : contractList) {
            Long contractId = contractEntity.getId();
            List<Long> outstockIdList = contractOutstockMap.get(contractId);
            List<OutstockProductEntity> outstockProductEntityList = contractOutstockProductMap.get(contractId);
            if (outstockProductEntityList == null) {
                outstockProductEntityList = new ArrayList<>();
            }
            for (OutstockProductEntity outstockProductEntity : outstockAllProductList) {
                Long outstockId = outstockProductEntity.getOutWarehouseId();
                if (outstockIdList.contains(outstockId)) {
                    outstockProductEntityList.add(outstockProductEntity);
                }
            }
            contractOutstockProductMap.put(contractId, outstockProductEntityList);
        }

        // 合同和关联产品的对应关系
        List<ContractProductEntity> contractProList = contractProductModel.getContractProductByContractIdIn(corpid, contractIdList);
        Map<Long, List<ContractProductEntity>> contractProductMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
        for (ContractEntityExt contractEntity : contractList) {
            Long contractId = contractEntity.getId();
            List<ContractProductEntity> contractProductList = contractProductMap.get(contractId);
            if (contractProductList == null) {
                contractProductList = new ArrayList<>();
            }
            for (ContractProductEntity contractProductEntity : contractProList) {
                if (Objects.equals(contractProductEntity.getContractId(), contractId)) {
                    contractProductList.add(contractProductEntity);
                }
            }
            contractProductMap.put(contractId, contractProductList);
        }

        // 合同那边的优化(将原合同属性变更)
        if (!oldContractIdIn.isEmpty()) {
            for (ContractEntityExt contractEntityExt : contractList) {
                if (contractEntityExt != null) {
                    JSONObject contractData = contractEntityExt.getData();
                    Long contractId = contractEntityExt.getId();

                    List<OutstockProductEntity> outstockProductList = contractOutstockProductMap.get(contractId);
                    List<ContractProductEntity> contractProductList = contractProductMap.get(contractId);

                    // 计算合同出库成本：SUM（已出库产品数量*出库产品成本）
                    double realCost = 0D;
                    boolean isOld = false;
                    // 合并的出库产品数量MAP
                    Map<Long, Double> outstockProductNumMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    // 行对应数量
                    Map<Long, Double> lineProductNumMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    for (OutstockProductEntity outstockProductEntity : outstockProductList) {
                        if (Objects.isNull(outstockProductEntity.getRefProductId())) {
                            isOld = true;
                        }
                        Long productId = outstockProductEntity.getProductId();
                        Double productNum = outstockProductEntity.getProductNum();
                        productNum = productNum == null ? 0D : productNum;
                        Double cost = outstockProductEntity.getCost();
                        cost = cost == null ? 0D : cost;
                        realCost = Arith.add(realCost, Arith.mul(productNum, cost));
                        if (outstockProductNumMap.containsKey(productId)) {
                            outstockProductNumMap.put(productId, Arith.add(outstockProductNumMap.get(productId), productNum));
                        } else {
                            outstockProductNumMap.put(productId, productNum);
                        }
                        if (!isOld) {
                            Long refProductId = outstockProductEntity.getRefProductId();
                            if (lineProductNumMap.containsKey(refProductId)) {
                                lineProductNumMap.put(refProductId, Arith.add(lineProductNumMap.get(refProductId), productNum));
                            } else {
                                lineProductNumMap.put(refProductId, productNum);
                            }
                        }
                    }

                    // 算出合同中每种产品的平均价
                    Map<Long, String> avgCostMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                    for (ContractProductEntity contractProductEntity : contractProductList) {
                        Long productId = contractProductEntity.getProductId();
                        Double productNum = contractProductEntity.getProductNum() == null ? 0D : Math.abs(contractProductEntity.getProductNum());
                        if (isOld) {
                            if (avgCostMap.containsKey(productId)) {
                                // map中已经有相同产品，需要计算平均值
                                String productInfo = avgCostMap.get(productId);
                                String[] split = productInfo.split(",");
                                Double preCost = StringUtil.toDouble((split[0]), 0D);
                                Double preNum = StringUtil.toDouble((split[1]), 0D);
                                Double nowCost = SaasProductHelp.calculateCost(preNum, preCost, productNum, contractProductEntity.getCost(), 1);
                                Double nowNum = Arith.add(preNum, productNum);
                                avgCostMap.put(productId, nowCost + "," + nowNum);
                            } else {
                                // 将产品id为key，合同产品平均价和数量拼接字符串为value存入map中
                                String productInfo = contractProductEntity.getCost() + "," + productNum;
                                avgCostMap.put(productId, productInfo);
                            }
                        } else if (lineProductNumMap.containsKey(contractProductEntity.getId())) {
                            // 分行已出库数量计算
                            contractProductEntity.setContractOutstockNum(lineProductNumMap.get(contractProductEntity.getId()));
                        }
                    }
                    double estimateCost = 0D;
                    if (isOld) {
                        // 老数据合同预估成本计算
                        for (ContractProductEntity contractProductEntity : contractProductList) {
                            String productInfo = avgCostMap.get(contractProductEntity.getProductId());
                            if (org.apache.commons.lang.StringUtils.isEmpty(productInfo)) {
                                continue;
                            }
                            String[] productInfos = productInfo.split(",");
                            if (outstockProductNumMap.containsKey(contractProductEntity.getProductId())) {
                                if (Arith.sub(contractProductEntity.getProductNum(), outstockProductNumMap.get(contractProductEntity.getProductId())) > 0) {
                                    estimateCost = Arith.add(estimateCost, Arith.mul(Arith.sub(contractProductEntity.getProductNum(), outstockProductNumMap.get(contractProductEntity.getProductId())), StringUtil.toDouble((productInfos[0]), 0D)));
                                }
                            } else {
                                estimateCost = Arith.add(estimateCost, Arith.mul(contractProductEntity.getProductNum(), StringUtil.toDouble((productInfos[0]), 0D)));
                            }
                        }
                    } else {
                        // 新数据合同预估成本计算
                        for (ContractProductEntity contractProductEntity : contractProductList) {
                            if (Arith.sub(contractProductEntity.getProductNum(), contractProductEntity.getContractOutstockNum()) > 0) {
                                estimateCost = Arith.add(estimateCost, Arith.mul(contractProductEntity.getCost(), Arith.sub(contractProductEntity.getProductNum(), contractProductEntity.getContractOutstockNum())));
                            }
                        }
                    }

                    Double surchargeAmount = FastJsonHelper.getDoubleOrDefaultFromFormData(contractData, ContractEnum.OTHER_EXPENSE.getAttr(), BasicConstant.ZERO_DOUBLE);
                    Double contractCost;
                    if(contractIdAndCostMap.containsKey(contractId)){
                        Double cost = contractIdAndCostMap.get(contractId) == null ? BasicConstant.ZERO_DOUBLE : contractIdAndCostMap.get(contractId);
                        contractCost = Arith.sub(Arith.add(Arith.add(estimateCost, realCost), surchargeAmount), cost);
                    } else {
                        contractCost = Arith.add(Arith.add(estimateCost, realCost), surchargeAmount);
                    }
                    // 合同成本 = 合同产品成本 - 退货产品成本（关联出库单的产品成本 = 红冲合同的合同成本）+ 其他费用
                    contractData.put(ContractEnum.CONTRACT_COST.getAttr(), Arith.round(contractCost, 2));

                    //合同毛利 = 合同金额 - 退货金额（关联计算）- 合同成本（同上）
                    Double amount = FastJsonHelper.getDoubleOrDefaultFromFormData(contractData, ContractEnum.AMOUNT.getAttr(), 0D);
                    Double grossProfit;
                    if(allContractCostMap.containsKey(contractId)){
                        Double cost = allContractCostMap.get(contractId) == null ? BasicConstant.ZERO_DOUBLE : allContractCostMap.get(contractId);
                        grossProfit = Arith.sub(Arith.sub(amount, contractCost), cost);
                    } else {
                        grossProfit = Arith.sub(amount, contractCost);
                    }
                    contractData.put(ContractEnum.GROSS_PROFIT.getAttr(), Arith.round(grossProfit, 2));
                    // 合同毛利率
                    if (Double.compare(amount, BasicConstant.ZERO_DOUBLE) != 0) {
                        contractData.put(ContractEnum.GROSS_PROFIT_RATE.getAttr(), Arith.round(Arith.div(grossProfit, amount), 4));
                    } else {
                        contractData.put(ContractEnum.GROSS_PROFIT_RATE.getAttr(), BasicConstant.ZERO_DOUBLE);
                    }

                    // 现金毛利 = 合同已收款金额 - 合同成本（同上）
                    Double finishAmount = FastJsonHelper.getDoubleOrDefaultFromFormData(contractData, ContractEnum.FINISH_AMOUNT.getAttr(), 0D);
                    Double cashProfit = Arith.sub(finishAmount, contractCost);
                    contractData.put(ContractEnum.CASH_PROFIT.getAttr(), cashProfit);
                    // 现金毛利率
                    if (Double.compare(finishAmount, BasicConstant.ZERO_DOUBLE) != 0) {
                        contractData.put(ContractEnum.CASH_PROFIT_RATE.getAttr(), Arith.round(Arith.div(cashProfit, finishAmount), 2));
                    } else {
                        contractData.put(ContractEnum.CASH_PROFIT_RATE.getAttr(), BasicConstant.ZERO_DOUBLE);
                    }
                    contractEntityExt.setData(contractData);
                    contractModel.update(contractEntityExt);
                }
            }
        }
        LOG.warn("consume:" + (DateTimeUtil.getInt() - start));
        LOG.warn("over");
        return "success";
    }

    /**
     * 将老公司的客户阶段部分状态设置成未勾选
     * @param companyRuleSetDTO
     * @param br
     * @return
     * @throws Exception
     */
    @RequestMapping(value = "/selectCompany", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String selectCompany(@RequestBody @Valid CompanyRuleSetDTO companyRuleSetDTO, BindingResult br) throws Exception {
        if (!proBaseConfig.getXbbCode().equals(companyRuleSetDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        long start = DateTimeUtil.getInt();
        LOG.warn("start:"+start);
        //获取公司id
        List<String> corpidList = companyRuleSetDTO.getCorpidList();
        if (CollectionsUtil.isEmpty(corpidList)) {
            corpidList = companyModel.getCorpidList();
        }
        LOG.info("共有" + corpidList.size() + "家公司需要刷");
        Integer i = 0;
        //遍历公司Id，通过companyModel根据公司的信息查询所有的公司实体
        for (String corpid : corpidList) {
            i++;
            LOG.info("现在是第" + i + "家公司,"+i+"/"+corpidList.size());
            Map<String, Object> params = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            params.put("corpid", corpid);
            params.put("del", BasicConstant.ZERO);
            params.put("businessType",XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode());
            //查询公司对应的表单id
            List<PaasFormEntityExt> paasFormEntityExtList = paasFormModel.list(params);
            if (CollectionsUtil.isEmpty(paasFormEntityExtList)) {
                continue;
            }

            //需要根据类型进行分类
            List<String> configList = new ArrayList<>();
            //获取客户阶段中的别名
            String stageJumpGoToTime = RuleSettingEnum.STAGE_JUMP_GO_TO_TIME.getConfig();
            String completePhaseWorkCompletionTime = RuleSettingEnum.COMPLETE_PHASE_WORK_COMPLETION_TIME.getConfig();
            String fillingInStageFeedbackCreateTime = RuleSettingEnum.FILLING_IN_STAGE_FEEDBACK_CREATE_TIME.getConfig();
            configList.add(stageJumpGoToTime);
            configList.add(completePhaseWorkCompletionTime);
            configList.add(fillingInStageFeedbackCreateTime);

            List<FormConfigEntity> formConfigEntityList = new ArrayList<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
            for (PaasFormEntityExt paasFormEntityExt : paasFormEntityExtList) {
                List<FormConfigEntity> formConfigEntity = formConfigModel.getButtonEntityByFormId(corpid, paasFormEntityExt.getId(), configList);
                Map<String, FormConfigEntity> formConfigEntityMap = new HashMap<>(PaasConstant.DEFAULT_INITIAL_CAPACITY);
                for (FormConfigEntity configEntity : formConfigEntity) {
                    formConfigEntityMap.put(configEntity.getConfig(), configEntity);
                }

                for (String str : configList) {
                    FormConfigEntity configEntity = formConfigEntityMap.get(str);
                    if (Objects.isNull(configEntity)) {
                        RuleSettingEnum ruleSettingEnum = RuleSettingEnum.getByConfig(str);
                        configEntity = new FormConfigEntity();
                        configEntity.setCorpid(corpid);
                        configEntity.setFormId(paasFormEntityExt.getId());
                        configEntity.setConfig(ruleSettingEnum.getConfig());
                        configEntity.setBusinessType(XbbRefTypeEnum.CUSTOMER_MANAGEMENT.getCode());
                        configEntity.setConfigValue("0");
                        formConfigEntityList.add(configEntity);
                    }
                }
            }
            if (CollectionsUtil.isNotEmpty(formConfigEntityList)) {
                formConfigModel.insertBatch(formConfigEntityList);
            }
        }
        //停留时长
        LOG.warn("consume:" + (DateTimeUtil.getInt() - start));
        LOG.warn("selectPCompany over");
        return "success";
    }

    /**
     * 更正合同成本，合同毛利描述信息
     */
    @RequestMapping(value = "/fixContractMemo", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String fixContractMemo(@RequestBody @Valid FixContractDTO allScriptDTO, BindingResult br) throws XbbException {
        if (!proBaseConfig.getXbbCode().equals(allScriptDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        XbbResponse<ScriptVO> response;
        if (br.hasErrors()) {
            String errMsg = Objects.requireNonNull(br.getFieldError()).getDefaultMessage();
            response = new XbbResponse<>(SystemErrorCodeEnum.API_ERROR_100002, errMsg);
        } else {
            try {
                ScriptVO scriptVO = repairExplainService.fixContractMemo(allScriptDTO);
                response = new XbbResponse<>(scriptVO);
            } catch (XbbException e) {
                response = new XbbResponse<>(e);
            }
        }
        return JSON.toJSONString(response);
    }

    /**
     * 修复三方数据id关联关系
     *
     * @param updateDataDTO
     * @param br
     * @return
     * @throws XbbException
     */
    @RequestMapping(value = "/fixFineCluePid", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String fixFineCluePid(@RequestBody @Valid UpdateDataDTO updateDataDTO, BindingResult br) throws XbbException {
        if (!proBaseConfig.getXbbCode().equals(updateDataDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        XbbResponse<ScriptVO> response;
        if (br.hasErrors()) {
            String errMsg = Objects.requireNonNull(br.getFieldError()).getDefaultMessage();
            response = new XbbResponse<>(SystemErrorCodeEnum.API_ERROR_100002, errMsg);
        } else {
            try {
                ScriptVO scriptVO = repairDataService.fixFineCluePid(updateDataDTO);
                response = new XbbResponse<>(scriptVO);
            } catch (XbbException e) {
                response = new XbbResponse<>(e);
            }
        }
        return JSON.toJSONString(response);
    }

    /**
     * 修复逍邦网络公司的客户错误数据
     * @param updateDataDTO
     * @param br
     * @return
     * @throws XbbException
     */
    @RequestMapping(value = "/fixCustomerDataForXbb", method = RequestMethod.POST, produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
    public String fixCustomerDataForXbb(@RequestBody @Valid UpdateDataDTO updateDataDTO, BindingResult br) throws XbbException {
        if (!proBaseConfig.getXbbCode().equals(updateDataDTO.getXbbCode())) {
            throw new XbbException(SystemErrorCodeEnum.API_ERROR_100006, SystemErrorCodeEnum.API_ERROR_100006.getMsg());
        }
        XbbResponse<ScriptVO> response;
        if (br.hasErrors()) {
            String errMsg = Objects.requireNonNull(br.getFieldError()).getDefaultMessage();
            response = new XbbResponse<>(SystemErrorCodeEnum.API_ERROR_100002, errMsg);
        } else {
            try {
                ScriptVO scriptVO = repairDataService.fixCustomerDataForXbb(updateDataDTO);
                response = new XbbResponse<>(scriptVO);
            } catch (XbbException e) {
                response = new XbbResponse<>(e);
            }
        }
        return JSON.toJSONString(response);
    }
}
